1 /*
2 * Copyright (c) 2025 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 <iostream>
17
18 #include "dm/display_manager.h"
19 #include "event_handler.h"
20 #include "rs_trace.h"
21 #include "securec.h"
22
23 #include "draw/canvas.h"
24 #include "image/bitmap.h"
25 #include "transaction/rs_interfaces.h"
26 #include "transaction/rs_transaction.h"
27 #include "ui/rs_canvas_node.h"
28 #include "ui/rs_root_node.h"
29 #include "ui/rs_surface_node.h"
30 #include "ui/rs_ui_context.h"
31 #include "ui/rs_ui_director.h"
32
33 using namespace OHOS;
34 using namespace OHOS::Rosen;
35 uint64_t screenId = 0;
36 const Rosen::RSAnimationTimingCurve ANIMATION_TIMING_CURVE =
37 Rosen::RSAnimationTimingCurve::CreateCubicCurve(0.2f, 0.0f, 0.2f, 1.0f);
38
39 namespace {
40
Init(std::shared_ptr<RSUIDirector> rsUiDirector,int width,int height,std::vector<std::shared_ptr<RSCanvasNode>> & nodes,std::shared_ptr<RSNode> & rootNode)41 void Init(std::shared_ptr<RSUIDirector> rsUiDirector, int width, int height,
42 std::vector<std::shared_ptr<RSCanvasNode>>& nodes, std::shared_ptr<RSNode>& rootNode)
43 {
44 std::cout << "rs multi instance demo Init Rosen Backend!" << std::endl;
45 auto rsUIContext = rsUiDirector->GetRSUIContext();
46 rootNode = RSRootNode::Create(false, false, rsUIContext);
47 rootNode->SetBounds(0, 0, width, height);
48 rootNode->SetFrame(0, 0, width, height);
49 rootNode->SetBackgroundColor(Drawing::Color::COLOR_YELLOW);
50
51 nodes.emplace_back(RSCanvasNode::Create(false, false, rsUIContext));
52 nodes[0]->SetBounds(0, 0, 100, 100);
53 nodes[0]->SetFrame(0, 0, 100, 100);
54 nodes[0]->SetBackgroundColor(Drawing::Color::COLOR_BLUE);
55
56 rootNode->AddChild(nodes[0], -1);
57
58 nodes.emplace_back(RSCanvasNode::Create(false, false, rsUIContext));
59 nodes[1]->SetBounds(0, 200, 100, 100);
60 nodes[1]->SetFrame(0, 200, 100, 100);
61 nodes[1]->SetBackgroundColor(Drawing::Color::COLOR_GREEN);
62
63 rootNode->AddChild(nodes[0], -1);
64 rootNode->AddChild(nodes[1], -1);
65 rsUiDirector->SetRSRootNode(rootNode->ReinterpretCastTo<RSRootNode>());
66 }
67
68 class SubThread {
69 public:
SubThread(uint32_t threadIndex)70 SubThread(uint32_t threadIndex) : threadIndex_(threadIndex) {}
71 ~SubThread() = default;
Start()72 void Start()
73 {
74 std::string name = "SubThread" + std::to_string(threadIndex_);
75 runner_ = AppExecFwk::EventRunner::Create(name);
76 handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
77 }
PostTask(const std::function<void ()> & task,const std::string & name=std::string ())78 void PostTask(const std::function<void()>& task, const std::string& name = std::string())
79 {
80 if (handler_) {
81 handler_->PostImmediateTask(task, name);
82 }
83 }
84
85 private:
86 std::shared_ptr<AppExecFwk::EventRunner> runner_ = nullptr;
87 std::shared_ptr<AppExecFwk::EventHandler> handler_ = nullptr;
88 uint32_t threadIndex_ = 0;
89 };
90
InitSurface()91 bool InitSurface()
92 {
93 SubThread subThread1 = SubThread(1);
94 SubThread subThread2 = SubThread(2);
95 subThread1.Start();
96 subThread2.Start();
97 std::shared_ptr<RSUIDirector> rsUiDirector;
98 std::shared_ptr<RSUIDirector> rsUiDirector2;
99 std::shared_ptr<RSNode> rootNode;
100 std::vector<std::shared_ptr<RSCanvasNode>> nodes;
101 std::shared_ptr<RSSurfaceNode> surfaceNode;
102 // stage 1
103 std::function<void()> task = [&rsUiDirector, &nodes, &rootNode, &surfaceNode]() {
104 std::cout << "Stage 1" << std::endl;
105 rsUiDirector = RSUIDirector::Create();
106 rsUiDirector->Init(true, true);
107 auto uiContext = rsUiDirector->GetRSUIContext();
108 if (uiContext) {
109 std::cout << "stage 1 RSUIDirector::Create success" << std::endl;
110 std::cout << "stage 1 get RSUIContext by RSUIDirector success" << std::endl;
111 std::cout << "stage 1 RSUIContext token is " << uiContext->GetToken() << std::endl;
112 } else {
113 std::cout << "RSUIContext::Create failed" << std::endl;
114 }
115 RSSurfaceNodeConfig surfaceNodeConfig;
116 surfaceNodeConfig.SurfaceNodeName = "AppMain_Window";
117 RSSurfaceNodeType surfaceNodeType = RSSurfaceNodeType::APP_WINDOW_NODE;
118 std::cout << "RSSurfaceNode::Create" << std::endl;
119 surfaceNode = RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType, true, false, uiContext);
120 std::cout << "Create node by RSUIContext success" << std::endl;
121 surfaceNode->SetFrameGravity(Gravity::RESIZE_ASPECT_FILL);
122 surfaceNode->SetPositionZ(RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
123 surfaceNode->SetBounds(0, 0, 600, 600);
124 surfaceNode->SetBackgroundColor(SK_ColorRED);
125 rsUiDirector->SetRSSurfaceNode(surfaceNode);
126 Init(rsUiDirector, 300, 300, nodes, rootNode);
127 surfaceNode->AttachToDisplay(screenId);
128 auto transaction = uiContext->GetRSTransaction();
129 if (!transaction) {
130 std::cout << "!transaction" << std::endl;
131 return;
132 }
133 transaction->FlushImplicitTransaction();
134 std::cout << "find node by nodeMap" << std::endl;
135 auto node11 = RSNodeMap::Instance().GetNode(rootNode->GetId());
136 std::string result = !!node11 ? "true" : "false";
137 std::cout << "find node by global nodeMap result is " << result << std::endl;
138 auto node32 = uiContext->GetNodeMap().GetNode(rootNode->GetId());
139 result = !!node32 ? "true" : "false";
140 std::cout << "find node by nodeMapnew result is " << result << std::endl;
141 // change property in nodes [setter using modifier]
142 sleep(2);
143 std::cout << "change Node properties " << std::endl;
144 nodes[0]->SetBounds(0, 0, 200, 200);
145 nodes[0]->SetFrame(0, 0, 200, 200);
146 nodes[0]->SetBorderColor(Drawing::Color::COLOR_BLACK);
147 nodes[0]->SetBorderWidth(10);
148 nodes[0]->SetBorderStyle((uint32_t)BorderStyle::SOLID);
149 std::cout << "send message by local transaction" << std::endl;
150 transaction->FlushImplicitTransaction();
151 sleep(3);
152 std::cout << "window1 animation start" << std::endl;
153 auto propertyCallback = [&]() {
154 std::cout << "window1 animation1 " << std::endl;
155 nodes[0]->SetBounds(100, 0, 100, 100);
156 nodes[0]->SetFrame(100, 0, 100, 100);
157 nodes[0]->SetBackgroundColor(Drawing::Color::COLOR_RED);
158 };
159 auto finishCallback = [&]() {};
160 RSAnimationTimingProtocol protocol;
161 protocol.SetDuration(1000);
162 RSNode::Animate(uiContext, protocol, ANIMATION_TIMING_CURVE, propertyCallback, finishCallback);
163 transaction->FlushImplicitTransaction();
164 sleep(6);
165 auto propertyCallback2 = [&]() {
166 std::cout << "window1 animation2" << std::endl;
167 nodes[0]->SetBounds(0, 0, 200, 200);
168 nodes[0]->SetFrame(0, 0, 200, 200);
169 nodes[0]->SetBackgroundColor(Drawing::Color::COLOR_BLACK);
170 };
171 auto finishCallback2 = [&]() {};
172 RSNode::Animate(uiContext, protocol, ANIMATION_TIMING_CURVE, propertyCallback2, finishCallback2);
173 transaction->FlushImplicitTransaction();
174 sleep(2);
175 std::cout << "window1 hide" << std::endl;
176 surfaceNode->SetVisible(false);
177 transaction->FlushImplicitTransaction();
178 };
179 subThread1.PostTask(task, "stage 1");
180 sleep(8);
181 // stage 2
182 std::shared_ptr<RSNode> rootNode2;
183 std::vector<std::shared_ptr<RSCanvasNode>> nodes2;
184 std::shared_ptr<RSSurfaceNode> surfaceNode2;
185 std::function<void()> task2 = [&rsUiDirector2, &nodes2, &rootNode2, &surfaceNode2, &nodes, &rootNode,
186 &rsUiDirector]() {
187 std::cout << " " << std::endl;
188 std::cout << "Stage 2" << std::endl;
189 rsUiDirector2 = RSUIDirector::Create();
190 rsUiDirector2->Init(true, true);
191 auto uiContext = rsUiDirector2->GetRSUIContext();
192 if (uiContext) {
193 std::cout << "stage 2 RSUIDirector::Create success" << std::endl;
194 std::cout << "stage 2 get RSUIContext by RSUIDirector success" << std::endl;
195 std::cout << "stage 2 RSUIContext token is " << uiContext->GetToken() << std::endl;
196 std::cout << "stage 2 token is not same as stage 1" << std::endl;
197 } else {
198 std::cout << "RSUIContext::Create failed" << std::endl;
199 }
200 // stage 2 find node
201 std::cout << "find node in thread B" << std::endl;
202 auto node32 = uiContext->GetNodeMap().GetNode(rootNode->GetId());
203 std::string result = !!node32 ? "true" : "false";
204 // change property by thread2
205 nodes[0]->SetBounds(0, 0, 400, 200);
206 nodes[0]->SetFrame(0, 0, 400, 200);
207 nodes[0]->SetBorderColor(Drawing::Color::COLOR_RED);
208 nodes[0]->SetBorderWidth(10);
209 nodes[0]->SetBorderStyle((uint32_t)BorderStyle::SOLID);
210 std::cout << "modifier property in thread 2 failed" << std::endl;
211 auto transaction = uiContext->GetRSTransaction();
212 transaction->FlushImplicitTransaction();
213 RSSurfaceNodeConfig surfaceNodeConfig;
214 surfaceNodeConfig.SurfaceNodeName = "AppMain_Window2";
215 RSSurfaceNodeType surfaceNodeType = RSSurfaceNodeType::APP_WINDOW_NODE;
216 std::cout << "stage 2 RSSurfaceNode::Create" << std::endl;
217 surfaceNode2 = RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType, true, false, uiContext);
218 surfaceNode2->SetFrameGravity(Gravity::RESIZE_ASPECT_FILL);
219 surfaceNode2->SetPositionZ(RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
220 surfaceNode2->SetBounds(700, 700, 600, 600);
221 surfaceNode2->SetBackgroundColor(SK_ColorRED);
222 rsUiDirector2->SetRSSurfaceNode(surfaceNode2);
223 Init(rsUiDirector2, 400, 400, nodes2, rootNode2);
224 surfaceNode2->AttachToDisplay(screenId);
225 auto uiContext2 = rsUiDirector->GetRSUIContext();
226 uiContext2->GetRSTransaction()->FlushImplicitTransaction();
227 sleep(1);
228 std::cout << "send Message By window1 flush failed" << std::endl;
229 transaction->FlushImplicitTransaction();
230 sleep(2);
231 std::cout << "window2 animation start" << std::endl;
232 auto propertyCallback = [&]() {
233 std::cout << "window2 animation " << std::endl;
234 nodes2[0]->SetBounds(100, 0, 100, 100);
235 nodes2[0]->SetFrame(100, 0, 100, 100);
236 nodes2[0]->SetBackgroundColor(Drawing::Color::COLOR_BLACK);
237 };
238 auto finishCallback = [&]() {};
239 RSAnimationTimingProtocol protocol;
240 protocol.SetDuration(1000);
241 RSNode::Animate(uiContext, protocol, ANIMATION_TIMING_CURVE, propertyCallback, finishCallback);
242 transaction->FlushImplicitTransaction();
243 sleep(3);
244 auto propertyCallback2 = [&]() {
245 std::cout << "window2 animation2" << std::endl;
246 nodes2[0]->SetBounds(0, 0, 200, 200);
247 nodes2[0]->SetFrame(0, 0, 200, 200);
248 nodes2[0]->SetBackgroundColor(Drawing::Color::COLOR_RED);
249 };
250 auto finishCallback2 = [&]() {};
251 RSNode::Animate(uiContext2, protocol, ANIMATION_TIMING_CURVE, propertyCallback2, finishCallback2);
252 transaction->FlushImplicitTransaction();
253 std::cout << "window2 animation2 failed because uiContext1 can not effect window2" << std::endl;
254 sleep(3);
255 std::cout << "window2 hide" << std::endl;
256 surfaceNode2->SetVisible(false);
257 transaction->FlushImplicitTransaction();
258 };
259 subThread2.PostTask(task2, "stage 2");
260 sleep(10);
261
262 // stage 3
263 std::shared_ptr<RSNode> rootNode3;
264 std::vector<std::shared_ptr<RSCanvasNode>> nodes3;
265 std::shared_ptr<RSSurfaceNode> surfaceNode3;
266 std::shared_ptr<RSNode> rootNode4;
267 std::vector<std::shared_ptr<RSCanvasNode>> nodes4;
268 std::shared_ptr<RSSurfaceNode> surfaceNode4;
269 std::shared_ptr<RSUIDirector> rsUiDirector3;
270 std::shared_ptr<RSUIDirector> rsUiDirector4;
271 std::function<void()> task3 = [&rsUiDirector3, &rootNode3, &rootNode4, &surfaceNode3, &surfaceNode4, &nodes3,
272 &rsUiDirector4, &nodes4] {
273 std::cout << " " << std::endl;
274 std::cout << "stage 3 " << std::endl;
275 rsUiDirector3 = RSUIDirector::Create();
276 rsUiDirector3->Init(true, true);
277 auto uiContext3 = rsUiDirector3->GetRSUIContext();
278 if (uiContext3) {
279 std::cout << "stage 3 RSUIDirector 1 success" << std::endl;
280 std::cout << "stage 3 RSUIContext token is " << uiContext3->GetToken() << std::endl;
281 } else {
282 std::cout << "RSUIContext::Create failed" << std::endl;
283 }
284 rsUiDirector4 = RSUIDirector::Create();
285 rsUiDirector4->Init(true, true);
286 auto uiContext4 = rsUiDirector4->GetRSUIContext();
287 if (uiContext4) {
288 std::cout << "stage 3 RSUIDirector 2 success" << std::endl;
289 std::cout << "stage 3 RSUIContext 2 token is " << uiContext4->GetToken() << std::endl;
290 std::cout << "stage 3 RsUIContext 2 token is not same as RSUIContext token" << std::endl;
291 } else {
292 std::cout << "RSUIContext::Create failed" << std::endl;
293 }
294 RSSurfaceNodeConfig surfaceNodeConfig;
295 surfaceNodeConfig.SurfaceNodeName = "AppMain_Window3";
296 RSSurfaceNodeType surfaceNodeType = RSSurfaceNodeType::APP_WINDOW_NODE;
297 std::cout << "stage 3 RSSurfaceNode::Create" << std::endl;
298 surfaceNode3 = RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType, true, false, uiContext3);
299 surfaceNode3->SetFrameGravity(Gravity::RESIZE_ASPECT_FILL);
300 surfaceNode3->SetPositionZ(RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
301 surfaceNode3->SetBounds(0, 1200, 600, 600);
302 surfaceNode3->SetBackgroundColor(SK_ColorRED);
303 rsUiDirector3->SetRSSurfaceNode(surfaceNode3);
304 Init(rsUiDirector3, 400, 400, nodes3, rootNode3);
305 surfaceNode3->AttachToDisplay(screenId);
306 RSSurfaceNodeConfig surfaceNodeConfig2;
307 surfaceNodeConfig2.SurfaceNodeName = "AppMain_Window4";
308 RSSurfaceNodeType surfaceNodeType2 = RSSurfaceNodeType::APP_WINDOW_NODE;
309 surfaceNode4 = RSSurfaceNode::Create(surfaceNodeConfig2, surfaceNodeType2, true, false, uiContext4);
310 surfaceNode4->SetFrameGravity(Gravity::RESIZE_ASPECT_FILL);
311 surfaceNode4->SetPositionZ(RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
312 surfaceNode4->SetBounds(900, 1200, 500, 500);
313 surfaceNode4->SetBackgroundColor(SK_ColorRED);
314 rsUiDirector4->SetRSSurfaceNode(surfaceNode4);
315 Init(rsUiDirector4, 300, 300, nodes4, rootNode4);
316 surfaceNode4->AttachToDisplay(screenId);
317 auto transaction3 = uiContext3->GetRSTransaction();
318 transaction3->FlushImplicitTransaction();
319 std::cout << "window 4 message flush failed because uicontext3 can not flush window4" << std::endl;
320 sleep(2);
321 auto transaction4 = uiContext4->GetRSTransaction();
322 transaction4->FlushImplicitTransaction();
323 std::cout << "window 4 message flush success" << std::endl;
324 sleep(2);
325 auto propertyCallback = [&]() {
326 std::cout << "window3 animation" << std::endl;
327 nodes3[0]->SetBounds(100, 0, 100, 100);
328 nodes3[0]->SetFrame(100, 0, 100, 100);
329 nodes3[0]->SetBackgroundColor(Drawing::Color::COLOR_BLACK);
330 };
331 auto finishCallback = [&]() {};
332 RSAnimationTimingProtocol protocol;
333 protocol.SetDuration(1000);
334 RSNode::Animate(uiContext3, protocol, ANIMATION_TIMING_CURVE, propertyCallback, finishCallback);
335 auto propertyCallback2 = [&]() {
336 std::cout << "window4 animation" << std::endl;
337 nodes4[0]->SetBounds(100, 0, 100, 100);
338 nodes4[0]->SetFrame(100, 0, 100, 100);
339 nodes4[0]->SetBackgroundColor(Drawing::Color::COLOR_BLACK);
340 };
341 auto finishCallback4 = [&]() {};
342 RSNode::Animate(uiContext3, protocol, ANIMATION_TIMING_CURVE, propertyCallback2, finishCallback4);
343 transaction3->FlushImplicitTransaction();
344 transaction4->FlushImplicitTransaction();
345 std::cout << "window 4 can not do animation" << std::endl;
346 sleep(2);
347 nodes3[1]->AddChild(nodes4[1], -1);
348 std::cout << "window 3 window 4 can't add tree" << std::endl;
349 sleep(2);
350 std::cout << "window3 hide" << std::endl;
351 surfaceNode3->SetVisible(false);
352 transaction3->FlushImplicitTransaction();
353 sleep(1);
354 std::cout << "window4 hide" << std::endl;
355 surfaceNode4->SetVisible(false);
356 transaction4->FlushImplicitTransaction();
357 };
358 subThread1.PostTask(task3, "stage 3");
359 sleep(10);
360 return true;
361 }
362 } // namespace
363
main()364 int main()
365 {
366 std::cout << "rs multi instance demo start!" << std::endl;
367 InitSurface();
368 std::cout << "rs multi instance demo end!" << std::endl;
369 return 0;
370 }