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