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