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 "core/common/container.h"
19 #ifdef ENABLE_ROSEN_BACKEND
20 #include "core/components_ng/render/adapter/rosen_render_context.h"
21 #include "transaction/rs_interfaces.h"
22 #endif
23
24 namespace {
25 #ifdef ENABLE_ROSEN_BACKEND
26 constexpr float ONE_SECOND_IN_NANO = 1000000000.0f;
27
GetDisplayRefreshRate()28 float GetDisplayRefreshRate()
29 {
30 return 60.0f;
31 }
32 #endif
33 } // namespace
34
35 namespace OHOS::Ace {
36
FormRenderWindow(RefPtr<TaskExecutor> taskExecutor,int32_t id)37 FormRenderWindow::FormRenderWindow(RefPtr<TaskExecutor> taskExecutor, int32_t id)
38 : taskExecutor_(taskExecutor), id_(id)
39 {
40 #ifdef ENABLE_ROSEN_BACKEND
41 ContainerScope scope(id);
42 auto container = Container::Current();
43 if (receiver_ == nullptr) {
44 auto& rsClient = Rosen::RSInterfaces::GetInstance();
45 frameRateLinker_ = Rosen::RSFrameRateLinker::Create();
46 receiver_ = rsClient.CreateVSyncReceiver("Form", frameRateLinker_ != nullptr ? frameRateLinker_->GetId() : 0);
47 if (receiver_ == nullptr) {
48 LOGE("Form Create VSync receiver failed.");
49 return;
50 }
51 receiver_->Init();
52 }
53
54 int64_t refreshPeriod = static_cast<int64_t>(ONE_SECOND_IN_NANO / GetDisplayRefreshRate());
55 onVsyncCallback_ = [weakTask = taskExecutor_, id = id_, refreshPeriod](
56 int64_t timeStampNanos, int64_t frameCount, void* data) {
57 auto taskExecutor = weakTask.Upgrade();
58 CHECK_NULL_VOID(taskExecutor);
59 auto onVsync = [id, timeStampNanos, frameCount, refreshPeriod] {
60 int64_t ts = GetSysTimestamp();
61 ContainerScope scope(id);
62 // use container to get window can make sure the window is valid
63 auto container = Container::Current();
64 CHECK_NULL_VOID(container);
65 auto window = container->GetWindow();
66 CHECK_NULL_VOID(window);
67 window->OnVsync(static_cast<uint64_t>(timeStampNanos), static_cast<uint64_t>(frameCount));
68 auto pipeline = container->GetPipelineContext();
69 if (pipeline) {
70 pipeline->OnIdle(std::min(ts, timeStampNanos) + refreshPeriod);
71 }
72 };
73
74 auto uiTaskRunner = SingleTaskExecutor::Make(taskExecutor, TaskExecutor::TaskType::JS);
75 if (uiTaskRunner.IsRunOnCurrentThread()) {
76 onVsync();
77 return;
78 }
79
80 taskExecutor->PostTask(onVsync, TaskExecutor::TaskType::UI, "ArkUIFormRenderWindowVsync", PriorityType::VIP);
81 };
82
83 frameCallback_.userData_ = nullptr;
84 frameCallback_.callbackWithId_ = onVsyncCallback_;
85
86 receiver_->RequestNextVSync(frameCallback_);
87
88 rsUIDirector_ = OHOS::Rosen::RSUIDirector::Create();
89 rsUIDirector_->Init();
90
91 std::string surfaceNodeName = "ArkTSCardNode";
92 struct Rosen::RSSurfaceNodeConfig surfaceNodeConfig = {.SurfaceNodeName = surfaceNodeName, .isSync = true};
93 rsSurfaceNode_ = OHOS::Rosen::RSSurfaceNode::Create(surfaceNodeConfig, true);
94 rsUIDirector_->SetRSSurfaceNode(rsSurfaceNode_);
95
96 rsUIDirector_->SetUITaskRunner([taskExecutor, id = id_](const std::function<void()>& task, uint32_t delay) {
97 ContainerScope scope(id);
98 CHECK_NULL_VOID(taskExecutor);
99 taskExecutor->PostDelayedTask(
100 task, TaskExecutor::TaskType::UI, delay, "ArkUIFormRenderServiceTask", PriorityType::HIGH);
101 }, id);
102 #else
103 taskExecutor_ = nullptr;
104 id_ = 0;
105 #endif
106 }
107
RequestFrame()108 void FormRenderWindow::RequestFrame()
109 {
110 #ifdef ENABLE_ROSEN_BACKEND
111 if (receiver_ != nullptr) {
112 receiver_->RequestNextVSync(frameCallback_);
113 }
114 #endif
115 }
116
Destroy()117 void FormRenderWindow::Destroy()
118 {
119 LOG_DESTROY();
120 #ifdef ENABLE_ROSEN_BACKEND
121 frameCallback_.userData_ = nullptr;
122 frameCallback_.callback_ = nullptr;
123 rsUIDirector_->Destroy();
124 rsUIDirector_.reset();
125 callbacks_.clear();
126 #endif
127 }
128
SetRootFrameNode(const RefPtr<NG::FrameNode> & root)129 void FormRenderWindow::SetRootFrameNode(const RefPtr<NG::FrameNode>& root)
130 {
131 CHECK_NULL_VOID(root);
132 #ifdef ENABLE_ROSEN_BACKEND
133 auto rosenRenderContext = AceType::DynamicCast<NG::RosenRenderContext>(root->GetRenderContext());
134 CHECK_NULL_VOID(rosenRenderContext);
135 if (rosenRenderContext->GetRSNode()) {
136 auto rootSRNode = rosenRenderContext->GetRSNode();
137 const auto& calcLayoutConstraint = root->GetLayoutProperty()->GetCalcLayoutConstraint();
138 auto width = static_cast<float>(calcLayoutConstraint->maxSize->Width()->GetDimension().Value());
139 auto height = static_cast<float>(calcLayoutConstraint->maxSize->Height()->GetDimension().Value());
140 rootSRNode->SetBounds(0, 0, width, height);
141 CHECK_NULL_VOID(rsUIDirector_);
142 rsUIDirector_->SetRoot(rosenRenderContext->GetRSNode()->GetId());
143 }
144 CHECK_NULL_VOID(rsUIDirector_);
145 rsUIDirector_->SendMessages();
146 #endif
147 }
148
OnShow()149 void FormRenderWindow::OnShow()
150 {
151 #ifdef ENABLE_ROSEN_BACKEND
152 Window::OnShow();
153 rsUIDirector_->GoForeground();
154 #endif
155 }
156
OnHide()157 void FormRenderWindow::OnHide()
158 {
159 #ifdef ENABLE_ROSEN_BACKEND
160 Window::OnHide();
161 #endif
162 }
163
FlushTasks()164 void FormRenderWindow::FlushTasks()
165 {
166 #ifdef ENABLE_ROSEN_BACKEND
167 rsUIDirector_->SendMessages();
168 #endif
169 }
170
FlushFrameRate(int32_t rate,int32_t animatorExpectedFrameRate,int32_t rateType)171 void FormRenderWindow::FlushFrameRate(int32_t rate, int32_t animatorExpectedFrameRate, int32_t rateType)
172 {
173 #ifdef ENABLE_ROSEN_BACKEND
174 if (frameRateLinker_ == nullptr) {
175 return;
176 }
177 decltype(frameRateData_) frameRateData{rate, animatorExpectedFrameRate, rateType};
178 if (frameRateData_ != frameRateData) {
179 frameRateData_ = frameRateData;
180 frameRateLinker_->UpdateFrameRateRange({0, RANGE_MAX_REFRESHRATE, rate, rateType}, animatorExpectedFrameRate);
181 }
182 #endif
183 }
184 } // namespace OHOS::Ace
185