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