• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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/components_ng/render/adapter/form_render_window.h"
17 
18 #include "base/log/frame_report.h"
19 #include "core/common/container.h"
20 #ifdef ENABLE_ROSEN_BACKEND
21 #include "core/components_ng/render/adapter/rosen_render_context.h"
22 #include "render_service_client/core/ui/rs_root_node.h"
23 #include "transaction/rs_interfaces.h"
24 #endif
25 
26 namespace {
27 #ifdef ENABLE_ROSEN_BACKEND
28 constexpr float ONE_SECOND_IN_NANO = 1000000000.0f;
29 
GetDisplayRefreshRate()30 float GetDisplayRefreshRate()
31 {
32     return 60.0f;
33 }
34 #endif
35 } // namespace
36 
37 namespace OHOS::Ace {
38 
39 #ifdef ENABLE_ROSEN_BACKEND
40 std::recursive_mutex FormRenderWindow::globalMutex_;
41 #endif
42 
FormRenderWindow(RefPtr<TaskExecutor> taskExecutor,int32_t id)43 FormRenderWindow::FormRenderWindow(RefPtr<TaskExecutor> taskExecutor, int32_t id)
44     : taskExecutor_(taskExecutor), id_(id)
45 {
46 #ifdef ENABLE_ROSEN_BACKEND
47     ContainerScope scope(id);
48     auto container = Container::Current();
49     if (container != nullptr) {
50         uiContentType_ = container->GetUIContentType();
51     }
52     if (receiver_ == nullptr) {
53         auto& rsClient = Rosen::RSInterfaces::GetInstance();
54         frameRateLinker_ = Rosen::RSFrameRateLinker::Create();
55         receiver_ = rsClient.CreateVSyncReceiver("Form", frameRateLinker_ != nullptr ? frameRateLinker_->GetId() : 0);
56         if (receiver_ == nullptr) {
57             LOGE("Form Create VSync receiver failed.");
58             return;
59         }
60         receiver_->Init();
61     }
62 
63     InitOnVsyncCallback();
64 
65     receiver_->RequestNextVSync(frameCallback_);
66 
67     rsUIDirector_ = OHOS::Rosen::RSUIDirector::Create();
68     {
69         std::lock_guard<std::recursive_mutex> lock(globalMutex_);
70         if (SystemProperties::GetMultiInstanceEnabled()) {
71             rsUIDirector_->Init(true, true); // Func Init Thread unsafe.
72         } else {
73             rsUIDirector_->Init(); // Func Init Thread unsafe.
74         }
75     }
76 
77     std::string surfaceNodeName = "ArkTSCardNode";
78     struct Rosen::RSSurfaceNodeConfig surfaceNodeConfig = {.SurfaceNodeName = surfaceNodeName, .isSync = true};
79     if (SystemProperties::GetMultiInstanceEnabled()) {
80         rsSurfaceNode_ = OHOS::Rosen::RSSurfaceNode::Create(surfaceNodeConfig, true, rsUIDirector_->GetRSUIContext());
81         rsUIDirector_->SetRSSurfaceNode(rsSurfaceNode_);
82         rsUIDirector_->SetUITaskRunner([taskExecutor, id = id_](const std::function<void()>& task, uint32_t delay) {
83             ContainerScope scope(id);
84             CHECK_NULL_VOID(taskExecutor);
85             taskExecutor->PostDelayedTask(
86                 task, TaskExecutor::TaskType::UI, delay, "ArkUIFormRenderServiceTask", PriorityType::HIGH);
87             }, 0, true);
88     } else {
89         rsSurfaceNode_ = OHOS::Rosen::RSSurfaceNode::Create(surfaceNodeConfig, true);
90         rsUIDirector_->SetRSSurfaceNode(rsSurfaceNode_);
91         rsUIDirector_->SetUITaskRunner([taskExecutor, id = id_](const std::function<void()>& task, uint32_t delay) {
92             ContainerScope scope(id);
93             CHECK_NULL_VOID(taskExecutor);
94             taskExecutor->PostDelayedTask(
95                 task, TaskExecutor::TaskType::UI, delay, "ArkUIFormRenderServiceTask", PriorityType::HIGH);
96             }, id);
97     }
98 #else
99     taskExecutor_ = nullptr;
100     id_ = 0;
101 #endif
102 }
103 
RequestFrame()104 void FormRenderWindow::RequestFrame()
105 {
106 #ifdef ENABLE_ROSEN_BACKEND
107     if (receiver_ != nullptr) {
108         if (uiContentType_ == UIContentType::DYNAMIC_COMPONENT) {
109             CHECK_NULL_VOID(!isRequestVsync_);
110             isRequestVsync_ = true;
111         }
112         receiver_->RequestNextVSync(frameCallback_);
113     }
114 #endif
115 }
116 
RecordFrameTime(uint64_t timeStamp,const std::string & name)117 void FormRenderWindow::RecordFrameTime(uint64_t timeStamp, const std::string& name)
118 {
119 #ifdef ENABLE_ROSEN_BACKEND
120     if (uiContentType_ == UIContentType::DYNAMIC_COMPONENT) {
121         CHECK_NULL_VOID(rsUIDirector_);
122         rsUIDirector_->SetTimeStamp(timeStamp, name);
123     }
124 #endif
125 }
126 
Destroy()127 void FormRenderWindow::Destroy()
128 {
129     TAG_LOGI(AceLogTag::ACE_FORM, "RenderWindow destroyed");
130 #ifdef ENABLE_ROSEN_BACKEND
131     frameCallback_.userData_ = nullptr;
132     frameCallback_.callback_ = nullptr;
133     rsSurfaceNode_ = nullptr;
134     if (rsUIDirector_) {
135         rsUIDirector_->Destroy();
136         rsUIDirector_.reset();
137     }
138     callbacks_.clear();
139 #endif
140 }
141 
SetRootFrameNode(const RefPtr<NG::FrameNode> & root)142 void FormRenderWindow::SetRootFrameNode(const RefPtr<NG::FrameNode>& root)
143 {
144     CHECK_NULL_VOID(root);
145 #ifdef ENABLE_ROSEN_BACKEND
146     auto rosenRenderContext = AceType::DynamicCast<NG::RosenRenderContext>(root->GetRenderContext());
147     CHECK_NULL_VOID(rosenRenderContext);
148     if (rosenRenderContext->GetRSNode()) {
149         auto rootSRNode = rosenRenderContext->GetRSNode();
150         const auto& calcLayoutConstraint = root->GetLayoutProperty()->GetCalcLayoutConstraint();
151         auto width = static_cast<float>(calcLayoutConstraint->maxSize->Width()->GetDimension().Value());
152         auto height = static_cast<float>(calcLayoutConstraint->maxSize->Height()->GetDimension().Value());
153         rootSRNode->SetBounds(0, 0, width, height);
154         CHECK_NULL_VOID(rsUIDirector_);
155         rsUIDirector_->SetRSRootNode(
156             Rosen::RSNode::ReinterpretCast<Rosen::RSRootNode>(rosenRenderContext->GetRSNode()));
157     }
158     CHECK_NULL_VOID(rsUIDirector_);
159     rsUIDirector_->SendMessages();
160 #endif
161 }
162 
OnShow()163 void FormRenderWindow::OnShow()
164 {
165 #ifdef ENABLE_ROSEN_BACKEND
166     Window::OnShow();
167     CHECK_NULL_VOID(rsUIDirector_);
168     rsUIDirector_->GoForeground();
169 #endif
170 }
171 
OnHide()172 void FormRenderWindow::OnHide()
173 {
174 #ifdef ENABLE_ROSEN_BACKEND
175     Window::OnHide();
176 #endif
177 }
178 
FlushTasks(std::function<void ()> callback)179 void FormRenderWindow::FlushTasks(std::function<void()> callback)
180 {
181 #ifdef ENABLE_ROSEN_BACKEND
182     CHECK_NULL_VOID(rsUIDirector_);
183     if (!callback) {
184         rsUIDirector_->SendMessages();
185     } else {
186         rsUIDirector_->SendMessages(callback);
187     }
188 #endif
189 }
190 
Lock()191 void FormRenderWindow::Lock()
192 {
193 }
194 
Unlock()195 void FormRenderWindow::Unlock()
196 {
197 }
198 
GetVSyncPeriod() const199 int64_t FormRenderWindow::GetVSyncPeriod() const
200 {
201     int64_t vSyncPeriod = 0;
202 #if defined(ENABLE_ROSEN_BACKEND) && defined(__OHOS__)
203     if (receiver_) {
204         receiver_->GetVSyncPeriod(vSyncPeriod);
205     }
206 #endif
207 
208     return vSyncPeriod;
209 }
210 
FlushFrameRate(int32_t rate,int32_t animatorExpectedFrameRate,int32_t rateType)211 void FormRenderWindow::FlushFrameRate(int32_t rate, int32_t animatorExpectedFrameRate, int32_t rateType)
212 {
213 #ifdef ENABLE_ROSEN_BACKEND
214     if (frameRateLinker_ == nullptr) {
215         return;
216     }
217     decltype(frameRateData_) frameRateData{rate, animatorExpectedFrameRate, rateType};
218     if (frameRateData_ != frameRateData) {
219         frameRateData_ = frameRateData;
220         auto rsUIContext = rsUIDirector_ ? rsUIDirector_->GetRSUIContext() : nullptr;
221         frameRateLinker_->UpdateFrameRateRange({0, RANGE_MAX_REFRESHRATE, rate, rateType},
222             animatorExpectedFrameRate, rsUIContext);
223     }
224 #endif
225 }
226 
InitOnVsyncCallback()227 void FormRenderWindow::InitOnVsyncCallback()
228 {
229 #ifdef ENABLE_ROSEN_BACKEND
230     int64_t refreshPeriod = static_cast<int64_t>(ONE_SECOND_IN_NANO / GetDisplayRefreshRate());
231     onVsyncCallback_ = [weakTask = taskExecutor_, id = id_, refreshPeriod](
232                            int64_t timeStampNanos, int64_t frameCount, void* data) {
233         auto taskExecutor = weakTask.Upgrade();
234         CHECK_NULL_VOID(taskExecutor);
235         auto onVsync = [id, timeStampNanos, frameCount, refreshPeriod] {
236             int64_t ts = GetSysTimestamp();
237             ContainerScope scope(id);
238             // use container to get window can make sure the window is valid
239             auto container = Container::Current();
240             CHECK_NULL_VOID(container);
241             bool isReportFrameEvent = false;
242             auto containerHandler = container->GetContainerHandler();
243             if (containerHandler) {
244                 isReportFrameEvent = containerHandler->GetHostConfig().isReportFrameEvent;
245             }
246             if (isReportFrameEvent) {
247                 FrameReport::GetInstance().ReportSchedEvent(
248                     FrameSchedEvent::UI_SCB_WORKER_BEGIN, {});
249             }
250             auto window = container->GetWindow();
251             CHECK_NULL_VOID(window);
252             window->OnVsync(static_cast<uint64_t>(timeStampNanos), static_cast<uint64_t>(frameCount));
253             auto pipeline = container->GetPipelineContext();
254             if (pipeline) {
255                 pipeline->OnIdle(std::min(ts, timeStampNanos) + refreshPeriod);
256             }
257             if (isReportFrameEvent) {
258                 FrameReport::GetInstance().ReportSchedEvent(
259                     FrameSchedEvent::UI_SCB_WORKER_END, {});
260             }
261         };
262 
263         ContainerScope scope(id);
264         auto uiTaskRunner = SingleTaskExecutor::Make(taskExecutor, TaskExecutor::TaskType::JS);
265         if (uiTaskRunner.IsRunOnCurrentThread()) {
266             onVsync();
267             return;
268         }
269 
270         taskExecutor->PostTask(onVsync, TaskExecutor::TaskType::UI, "ArkUIFormRenderWindowVsync", PriorityType::VIP);
271     };
272 
273     frameCallback_.userData_ = nullptr;
274     frameCallback_.callbackWithId_ = onVsyncCallback_;
275 #endif
276 }
277 
278 } // namespace OHOS::Ace
279