1 /*
2 * Copyright (c) 2021-2022 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 #include <surface.h>
18
19 #include "command/rs_base_node_command.h"
20 #include "command/rs_display_node_command.h"
21 #include "command/rs_surface_node_command.h"
22 #include "common/rs_common_def.h"
23 #include "pipeline/rs_render_result.h"
24 #include "pipeline/rs_render_thread.h"
25 #include "ui/rs_canvas_node.h"
26 #include "ui/rs_surface_extractor.h"
27 #include "ui/rs_ui_director.h"
28 #include "transaction/rs_interfaces.h"
29 #include "ui/rs_display_node.h"
30 #include "ui/rs_surface_node.h"
31 #include "render_context/render_context.h"
32 // temporary debug
33 #include "foundation/graphic/graphic_2d/rosen/modules/render_service_base/src/platform/ohos/rs_surface_frame_ohos.h"
34 #include "foundation/graphic/graphic_2d/rosen/modules/render_service_base/src/platform/ohos/rs_surface_ohos.h"
35
36 using namespace OHOS;
37 using namespace OHOS::Rosen;
38 using namespace std;
39
40 namespace OHOS::Rosen {
41 namespace {
42 constexpr int SURFACE_NODE_SIZE = 100;
43 constexpr int SLEEP_TIME = 8;
44 }
45 #ifdef RS_ENABLE_GPU
46 RenderContext* rc_ = nullptr;
47 #endif
48
49 namespace pipelineTestUtils {
50 constexpr bool wrongExit = false;
51 constexpr bool successExit = false;
52 struct Circle {
CircleOHOS::Rosen::pipelineTestUtils::Circle53 Circle(float x, float y, float r)
54 :x_(x), y_(y), r_(r) {};
55 float x_ = 0.0f;
56 float y_ = 0.0f;
57 float r_ = 0.0f;
58 }; // class Circle
59
60 class ToDrawSurface {
61 public:
62 using drawFun = std::function<void(Drawing::Canvas&, Drawing::Brush&)>;
ToDrawSurface()63 ToDrawSurface() {};
64
SetSurfaceNode(const std::shared_ptr<RSSurfaceNode> surfaceNode)65 inline ToDrawSurface& SetSurfaceNode(const std::shared_ptr<RSSurfaceNode> surfaceNode)
66 {
67 surfaceNode_ = surfaceNode;
68 return *this;
69 }
70
SetSurfaceNodeSize(Drawing::Rect surfaceGeometry)71 inline ToDrawSurface& SetSurfaceNodeSize(Drawing::Rect surfaceGeometry)
72 {
73 surfaceGeometry_ = surfaceGeometry;
74 return *this;
75 }
76
SetBufferSize(int width,int height)77 inline ToDrawSurface& SetBufferSize(int width, int height)
78 {
79 bufferSize_ = Drawing::Rect(0, 0, width, height);
80 return *this;
81 }
82
SetBufferSizeAuto()83 inline ToDrawSurface& SetBufferSizeAuto()
84 {
85 bufferSize_ = surfaceGeometry_;
86 return *this;
87 }
88
SetBufferSize(Drawing::Rect bufferSize)89 inline ToDrawSurface& SetBufferSize(Drawing::Rect bufferSize)
90 {
91 // bufferSize has no XY
92 bufferSize_ = bufferSize;
93 return *this;
94 }
95
SetShapeColor(uint32_t color)96 inline ToDrawSurface& SetShapeColor(uint32_t color)
97 {
98 color_ = color;
99 return *this;
100 }
101
SetDraw(drawFun drawShape)102 inline ToDrawSurface& SetDraw(drawFun drawShape)
103 {
104 drawShape_ = drawShape;
105 return *this;
106 }
107
Run()108 bool Run()
109 {
110 printf("ToDrawSurface::Run() start\n");
111 if (surfaceNode_ == nullptr) {
112 printf("DrawSurface: surfaceNode_ is nullptr\n");
113 return false;
114 }
115 auto x = surfaceGeometry_.GetLeft();
116 auto y = surfaceGeometry_.GetTop();
117 auto width = surfaceGeometry_.GetWidth();
118 auto height = surfaceGeometry_.GetHeight();
119 surfaceNode_->SetBounds(x, y, width, height);
120 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode_);
121 if (rsSurface == nullptr) {
122 return wrongExit;
123 }
124 #ifdef RS_ENABLE_GPU
125 // SetRenderContext must before rsSurface->RequestFrame, or it will failed.
126 if (rc_) {
127 rsSurface->SetRenderContext(rc_);
128 } else {
129 printf("DrawSurface: RenderContext is nullptr\n");
130 }
131 #endif
132 auto framePtr = rsSurface->RequestFrame(bufferSize_.GetWidth(), bufferSize_.GetHeight());
133 if (!framePtr) {
134 // SetRenderContext must before rsSurface->RequestFrame,
135 // or frameptr will be nullptr.
136 printf("DrawSurface: frameptr is nullptr\n");
137 return wrongExit;
138 }
139 auto canvas = framePtr->GetCanvas();
140 if (!canvas) {
141 printf("DrawSurface: canvas is nullptr\n");
142 return wrongExit;
143 }
144 canvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
145 Drawing::Brush brush;
146 brush.SetAntiAlias(true);
147 brush.SetColor(color_);
148 if (!drawShape_) {
149 printf("DrawSurface: drawShape_ is nullptr\n");
150 return wrongExit;
151 }
152 drawShape_(*canvas, brush);
153 framePtr->SetDamageRegion(0, 0, surfaceGeometry_.GetWidth(), surfaceGeometry_.GetHeight());
154 rsSurface->FlushFrame(framePtr);
155 return successExit;
156 }
157 private:
158 Drawing::Rect surfaceGeometry_ = {0.f, 0.f, 0.f, 0.f};
159 Drawing::Rect bufferSize_ = {0.f, 0.f, 0.f, 0.f};
160 drawFun drawShape_;
161 uint32_t color_ = 0;
162 std::shared_ptr<RSSurfaceNode> surfaceNode_ = nullptr;
163 }; // class ToDrawSurface
164
CreateSurface()165 static std::shared_ptr<RSSurfaceNode> CreateSurface()
166 {
167 RSSurfaceNodeConfig config;
168 return RSSurfaceNode::Create(config);
169 }
170 } // namespace pipelineTestUtils
171
172 // Toy DMS.
173 using DisplayId = ScreenId;
174 class DmsMock {
175 private:
176 struct Display {
177 DisplayId id;
178 RSScreenModeInfo activeMode;
179 };
180 std::unordered_map<DisplayId, Display> displays_;
181 mutable std::recursive_mutex mutex_;
182 RSInterfaces& rsInterface_;
183 DisplayId defaultDisplayId_;
184
DmsMock()185 DmsMock() : rsInterface_(RSInterfaces::GetInstance())
186 {
187 Init();
188 }
189
Init()190 void Init()
191 {
192 std::lock_guard<std::recursive_mutex> lock(mutex_);
193 (void)rsInterface_.SetScreenChangeCallback([this](ScreenId id, ScreenEvent event) {
194 switch (event) {
195 case ScreenEvent::CONNECTED: {
196 this->OnDisplayConnected(id);
197 break;
198 }
199 case ScreenEvent::DISCONNECTED: {
200 this->OnDisplayDisConnected(id);
201 break;
202 }
203 default:
204 break;
205 }
206 });
207
208 defaultDisplayId_ = rsInterface_.GetDefaultScreenId();
209 displays_[defaultDisplayId_] =
210 Display { defaultDisplayId_, rsInterface_.GetScreenActiveMode(defaultDisplayId_) };
211 }
212
213 public:
GetInstance()214 inline static DmsMock& GetInstance()
215 {
216 static DmsMock c;
217 return c;
218 }
219
220 ~DmsMock() noexcept = default;
221
GetDefaultDisplayId() const222 DisplayId GetDefaultDisplayId() const
223 {
224 std::lock_guard<std::recursive_mutex> lock(mutex_);
225 return defaultDisplayId_;
226 }
227
GetDisplayActiveMode(DisplayId id) const228 std::optional<RSScreenModeInfo> GetDisplayActiveMode(DisplayId id) const
229 {
230 std::lock_guard<std::recursive_mutex> lock(mutex_);
231 if (displays_.count(id) == 0) {
232 cout << "DmsMock: No display " << id << "!" << endl;
233 return {};
234 }
235 return displays_.at(id).activeMode;
236 }
237
OnDisplayConnected(ScreenId id)238 void OnDisplayConnected(ScreenId id)
239 {
240 std::lock_guard<std::recursive_mutex> lock(mutex_);
241 displays_[id] = Display { id, rsInterface_.GetScreenActiveMode(id) };
242 std::cout << "DmsMock: Display " << id << " connected." << endl;
243 }
244
OnDisplayDisConnected(ScreenId id)245 void OnDisplayDisConnected(ScreenId id)
246 {
247 std::lock_guard<std::recursive_mutex> lock(mutex_);
248 if (displays_.count(id) == 0) {
249 cout << "DmsMock: No display " << id << "!" << endl;
250 } else {
251 std::cout << "DmsMock: Display " << id << " disconnected." << endl;
252 displays_.erase(id);
253 if (id == defaultDisplayId_) {
254 defaultDisplayId_ = rsInterface_.GetDefaultScreenId();
255 std::cout << "DmsMock: DefaultDisplayId changed, new DefaultDisplayId is" << defaultDisplayId_ << "."
256 << endl;
257 }
258 }
259 }
260 }; // class DmsMock
261
262 class RSDemoTestCase {
263 public:
GetInstance()264 inline static RSDemoTestCase& GetInstance()
265 {
266 static RSDemoTestCase c;
267 return c;
268 }
269
TestInit()270 void TestInit()
271 {
272 isInit_ = true;
273 std::cout << "Render service Client rs Demo.cpp testInit Start\n";
274
275 #ifdef RS_ENABLE_GPU
276 std::cout << "RS_ENABLE_GPU is enabled\n";
277 isGPU_ = true;
278 #else
279 std::cout << "RS_ENABLE_GPU is disabled\n";
280 isGPU_ = false;
281 #endif
282
283 DisplayId id = DmsMock::GetInstance().GetDefaultDisplayId();
284 std::cout << "RS default screen id is " << id << ".\n";
285 auto activeModeInfo = DmsMock::GetInstance().GetDisplayActiveMode(id);
286 if (activeModeInfo) {
287 screenWidth_ = activeModeInfo->GetScreenWidth();
288 screenheight_ = activeModeInfo->GetScreenHeight();
289 screenRefreshRate_ = static_cast<int>(activeModeInfo->GetScreenRefreshRate());
290 std::cout << "Display " << id << " active mode info:\n";
291 std::cout << "Width: " << screenWidth_ << ", Height: " << screenheight_;
292 std::cout << ", RefreshRate: " << screenRefreshRate_ << "Hz.\n";
293 } else {
294 std::cout << "Display " << id << " has no active mode!\n";
295 }
296 RenderContextInit();
297 std::cout << "Render service Client rs Demo.cpp testInit end\n";
298 std::cout << "-------------------------------------------------------\n";
299 return;
300 }
301
TestCaseDefault()302 void TestCaseDefault()
303 {
304 std::cout << "-------------------------------------------------------\n";
305 std::cout << "Render service Client rs Demo.cpp testCaseDefault Start\n";
306 auto surfaceNode1 = pipelineTestUtils::CreateSurface();
307 auto surfaceNode2 = pipelineTestUtils::CreateSurface();
308
309 pipelineTestUtils::ToDrawSurface()
310 .SetSurfaceNode(surfaceNode1)
311 .SetShapeColor(0xff00ffff)
312 .SetSurfaceNodeSize(Drawing::Rect(SURFACE_NODE_SIZE, 0,
313 screenWidth_ * 0.4f + SURFACE_NODE_SIZE, screenheight_ * 0.3f))
314 .SetBufferSizeAuto()
315 .SetDraw([&](Drawing::Canvas &canvas, Drawing::Brush &brush) -> void {
316 canvas.AttachBrush(brush);
317 canvas.DrawRect(Drawing::Rect(0, 0, screenWidth_ * 0.4f, screenheight_ * 0.3f));
318 canvas.DetachBrush();
319 })
320 .Run();
321
322 pipelineTestUtils::ToDrawSurface()
323 .SetSurfaceNode(surfaceNode2)
324 .SetShapeColor(0xffff0000)
325 .SetSurfaceNodeSize(Drawing::Rect(SURFACE_NODE_SIZE, screenheight_ * 0.8f,
326 screenWidth_ * 0.4f + SURFACE_NODE_SIZE, screenheight_))
327 .SetBufferSizeAuto()
328 .SetDraw([&](Drawing::Canvas &canvas, Drawing::Brush &brush) -> void {
329 canvas.AttachBrush(brush);
330 canvas.DrawRect(Drawing::Rect(0, 0, screenWidth_ * 0.4f, screenheight_ * 0.2f));
331 canvas.DetachBrush();
332 })
333 .Run();
334
335 RSDisplayNodeConfig config;
336 RSDisplayNode::SharedPtr displayNode = RSDisplayNode::Create(config);
337 displayNode->AddChild(surfaceNode1, -1);
338 displayNode->AddChild(surfaceNode2, -1);
339
340 auto transactionProxy = RSTransactionProxy::GetInstance();
341 if (transactionProxy != nullptr) {
342 transactionProxy->FlushImplicitTransaction();
343 }
344 sleep(SLEEP_TIME);
345 displayNode->RemoveFromTree();
346 if (transactionProxy != nullptr) {
347 transactionProxy->FlushImplicitTransaction();
348 }
349 std::cout << "Render service Client rs Demo.cpp testCaseDefault end\n";
350 std::cout << "-------------------------------------------------------\n";
351 }
352 private:
353 RSDemoTestCase() = default;
RenderContextInit()354 static void RenderContextInit()
355 {
356 #ifdef RS_ENABLE_GPU
357 std::cout << "RS_ENABLE_GPU is true. \n";
358 std::cout << "Init RenderContext start. \n";
359 rc_ = RenderContextFactory::GetInstance().CreateEngine();
360 if (rc_) {
361 std::cout << "Init RenderContext success.\n";
362 rc_->InitializeEglContext();
363 } else {
364 std::cout << "Init RenderContext failed, RenderContext is nullptr.\n";
365 }
366 std::cout << "Init RenderContext start.\n";
367 #endif
368 }
369
370 bool isInit_ = false;
371 bool isGPU_ = false;
372 int screenWidth_ = 0;
373 int screenheight_ = 0;
374 int screenRefreshRate_ = 0;
375 }; // class RSDemoTestCase
376 } // namespace OHOS::Rosen
377
main()378 int main()
379 {
380 RSDemoTestCase::GetInstance().TestInit();
381 RSDemoTestCase::GetInstance().TestCaseDefault();
382 return 0;
383 }
384