• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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