1 /*
2  * Copyright (c) 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 
24 #include "pipeline/rs_render_result.h"
25 #include "pipeline/rs_render_thread.h"
26 #include "transaction/rs_interfaces.h"
27 #include "ui/rs_canvas_node.h"
28 #include "ui/rs_surface_extractor.h"
29 #include "ui/rs_ui_director.h"
30 #include "ui/rs_display_node.h"
31 #include "ui/rs_surface_node.h"
32 #include "render_context/render_context.h"
33 // temporary debug
34 #include "foundation/graphic/graphic_2d/rosen/modules/render_service_base/src/platform/ohos/rs_surface_frame_ohos.h"
35 #include "foundation/graphic/graphic_2d/rosen/modules/render_service_base/src/platform/ohos/rs_surface_ohos.h"
36 
37 using namespace OHOS;
38 using namespace OHOS::Rosen;
39 using namespace std;
40 
41 namespace OHOS::Rosen {
42 #ifdef RS_ENABLE_GPU
43     RenderContext* rc_ = nullptr;
44 #endif
45 constexpr int SURFACE_NODE_SIZE = 100;
46 
47 namespace pipelineTestUtils {
48     constexpr bool wrongExit = false;
49     constexpr bool successExit = false;
50 
51     class ToDrawSurface {
52     public:
53         using drawFun = std::function<void(Drawing::Canvas&, Drawing::Brush&)>;
ToDrawSurface()54         ToDrawSurface()
55         {
56             // Do not hold it. Use it As ToDrawSurface::Sample().
57         };
58 
SetSurfaceNode(const std::shared_ptr<RSSurfaceNode> surfaceNode)59         inline ToDrawSurface& SetSurfaceNode(const std::shared_ptr<RSSurfaceNode> surfaceNode)
60         {
61             surfaceNode_ = surfaceNode;
62             return *this;
63         }
64 
SetSurfaceNodeSize(Drawing::Rect surfaceGeometry)65         inline ToDrawSurface& SetSurfaceNodeSize(Drawing::Rect surfaceGeometry)
66         {
67             surfaceGeometry_ = surfaceGeometry;
68             return *this;
69         }
70 
SetBufferSize(int width,int height)71         inline ToDrawSurface& SetBufferSize(int width, int height)
72         {
73             bufferSize_ = Drawing::Rect(0, 0, width, height);
74             return *this;
75         }
76 
SetBufferSizeAuto()77         inline ToDrawSurface& SetBufferSizeAuto()
78         {
79             bufferSize_ = surfaceGeometry_;
80             return *this;
81         }
82 
SetBufferSize(Drawing::Rect bufferSize)83         inline ToDrawSurface& SetBufferSize(Drawing::Rect bufferSize)
84         {
85             // bufferSize has no XY
86             bufferSize_ = bufferSize;
87             return *this;
88         }
89 
SetShapeColor(uint32_t color)90         inline ToDrawSurface& SetShapeColor(uint32_t color)
91         {
92             color_ = color;
93             return *this;
94         }
95 
SetDraw(drawFun drawShape)96         inline ToDrawSurface& SetDraw(drawFun drawShape)
97         {
98             drawShape_ = drawShape;
99             return *this;
100         }
101 
Run()102         bool Run()
103         {
104             if (surfaceNode_ == nullptr) {
105                 return false;
106             }
107             auto x = surfaceGeometry_.GetLeft();
108             auto y = surfaceGeometry_.GetTop();
109             auto width = surfaceGeometry_.GetWidth();
110             auto height = surfaceGeometry_.GetHeight();
111             surfaceNode_->SetBounds(x, y, width, height);
112             std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode_);
113             if (rsSurface == nullptr) {
114                 return wrongExit;
115             }
116 #ifdef RS_ENABLE_GPU
117             // SetRenderContext must before rsSurface->RequestFrame, or it will failed.
118             if (rc_) {
119                 rsSurface->SetRenderContext(rc_);
120             } else {
121                 cout << "DrawSurface: RenderContext is nullptr\n";
122             }
123 #endif
124             auto framePtr = rsSurface->RequestFrame(bufferSize_.GetWidth(), bufferSize_.GetHeight());
125             if (!framePtr) {
126                 // SetRenderContext must before rsSurface->RequestFrame,
127                 //      or frameptr will be nullptr.
128                 cout << "DrawSurface: frameptr is nullptr\n";
129                 return wrongExit;
130             }
131             auto canvas = framePtr->GetCanvas();
132             if (!canvas) {
133                 cout << "DrawSurface: canvas is nullptr\n";
134                 return wrongExit;
135             }
136             canvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
137             Drawing::Brush brush;
138             brush.SetAntiAlias(true);
139             brush.SetColor(color_);
140             if (!drawShape_) {
141                 cout << "DrawSurface: drawShape_ is nullptr\n";
142                 return wrongExit;
143             }
144             drawShape_(*(canvas), brush);
145             framePtr->SetDamageRegion(0, 0, surfaceGeometry_.GetWidth(), surfaceGeometry_.GetHeight());
146             rsSurface->FlushFrame(framePtr);
147             return successExit;
148         }
149     private:
150         Drawing::Rect surfaceGeometry_ = {0.f, 0.f, 0.f, 0.f};
151         Drawing::Rect bufferSize_ = {0.f, 0.f, 0.f, 0.f};
152         drawFun drawShape_;
153         uint32_t color_ = 0;
154         std::shared_ptr<RSSurfaceNode> surfaceNode_ = nullptr;
155     }; // class ToDrawSurface
156 
CreateSurface(int surfaceNodeX,int surfaceNodeY,int surfaceNodeWidth,int surfaceNodeHeight,uint32_t shapeColor)157     static std::shared_ptr<RSSurfaceNode> CreateSurface(int surfaceNodeX, int surfaceNodeY,
158         int surfaceNodeWidth, int surfaceNodeHeight, uint32_t shapeColor)
159     {
160         RSSurfaceNodeConfig config;
161         auto surfaceNode = RSSurfaceNode::Create(config);
162 
163         ToDrawSurface()
164             .SetSurfaceNode(surfaceNode)
165             .SetShapeColor(shapeColor)
166             .SetSurfaceNodeSize(Drawing::Rect(surfaceNodeX, surfaceNodeY,
167                 surfaceNodeWidth + surfaceNodeX, surfaceNodeHeight + surfaceNodeY))
168             .SetBufferSizeAuto()
169             .SetDraw([&](Drawing::Canvas &canvas, Drawing::Brush &brush) -> void {
170                 canvas.AttachBrush(brush);
171                 canvas.DrawRect(Drawing::Rect(0, 0, surfaceNodeWidth, surfaceNodeHeight));
172                 canvas.DetachBrush();
173             })
174             .Run();
175 
176         return surfaceNode;
177     }
178 
CreateDisplayNode(std::shared_ptr<RSSurfaceNode> surfaceNode)179     static std::shared_ptr<RSDisplayNode> CreateDisplayNode(std::shared_ptr<RSSurfaceNode> surfaceNode)
180     {
181         RSDisplayNodeConfig displayConfig;
182         RSDisplayNode::SharedPtr displayNode = RSDisplayNode::Create(displayConfig);
183         displayNode->AddChild(surfaceNode, -1);
184         return displayNode;
185     }
186 } // namespace pipelineTestUtils
187 
188 // This test case is designed for temporary result demonstration.
189 // It could be removed after DMS implements this feature.
190 class RSDisplayModeTestCase {
191 public:
GetInstance()192     inline static RSDisplayModeTestCase& GetInstance()
193     {
194         static RSDisplayModeTestCase c;
195         return c;
196     }
197 
GetOrSetDisplayMode(RSDisplayNode::SharedPtr targetDisplayNode,RSDisplayNode::SharedPtr sourceDisplayNode)198     void GetOrSetDisplayMode(RSDisplayNode::SharedPtr targetDisplayNode, RSDisplayNode::SharedPtr sourceDisplayNode)
199     {
200         auto transactionProxy = RSTransactionProxy::GetInstance();
201         while (true) {
202             int testType = -1;
203             int param = -1;
204 
205             cout << " ---------------------loop start------------------------" << endl;
206             cout << "Input test type, 1: Get, 0: Set:, Others: End Test " << endl;
207             cin >> testType;
208             if (testType != 1 && testType != 0) {
209                 return;
210             }
211             if (testType == 0) {
212                 cout << "Input param, 1: is mirror, 0: not mirror: " << endl;
213                 cin >> param;
214             }
215             cout << " " << endl;
216 
217             if (testType == 1) {
218                 auto isMirrorDisplay = targetDisplayNode->IsMirrorDisplay() ? "is mirror" : "not mirror";
219                 cout << "Get display mode result: "<< isMirrorDisplay << endl;
220             } else if (testType == 0) {
221                 bool isMirrored = param == 1 ? true : false;
222                 RSDisplayNodeConfig config = {0, isMirrored, sourceDisplayNode->GetId()};
223                 cout << "Set display mode "<< isMirrored << " , source node id " << config.mirrorNodeId << endl;
224                 targetDisplayNode->SetDisplayNodeMirrorConfig(config);
225             }
226 
227             if (transactionProxy != nullptr) {
228                 transactionProxy->FlushImplicitTransaction();
229             }
230         }
231         return;
232     }
233 
InitTestCase()234     void InitTestCase()
235     {
236         ScreenId id = RSInterfaces::GetInstance().GetDefaultScreenId();
237         auto activeModeInfo = RSInterfaces::GetInstance().GetScreenActiveMode(id);
238 
239         screenWidth_ = activeModeInfo.GetScreenWidth();
240         screenHeight_ = activeModeInfo.GetScreenHeight();
241         std::cout << "Display " << id << " active mode info:\n";
242         std::cout << "Width: " << screenWidth_ << ", Height: " << screenHeight_;
243 
244         RenderContextInit();
245     }
246 
TestCaseDefault()247     void TestCaseDefault()
248     {
249         auto sourceSurcaseNode = pipelineTestUtils::CreateSurface(SURFACE_NODE_SIZE, screenHeight_ * 0.2f,
250             screenWidth_ * 0.4f, screenHeight_ * 0.3f, 0xff0000ff);
251         auto sourceDisplayNode = pipelineTestUtils::CreateDisplayNode(sourceSurcaseNode);
252         auto targetSurfaceNode = pipelineTestUtils::CreateSurface(SURFACE_NODE_SIZE, screenHeight_ * 0.6f,
253             screenWidth_ * 0.6f, screenHeight_ * 0.3f, 0xffff0000);
254         auto targetDisplayNode = pipelineTestUtils::CreateDisplayNode(targetSurfaceNode);
255 
256         auto transactionProxy = RSTransactionProxy::GetInstance();
257         if (transactionProxy != nullptr) {
258             transactionProxy->FlushImplicitTransaction();
259         }
260 
261         GetOrSetDisplayMode(targetDisplayNode, sourceDisplayNode);
262 
263         sourceDisplayNode->RemoveFromTree();
264         targetDisplayNode->RemoveFromTree();
265 
266         if (transactionProxy != nullptr) {
267             transactionProxy->FlushImplicitTransaction();
268         }
269     }
270 private:
271     RSDisplayModeTestCase() = default;
RenderContextInit()272     void RenderContextInit()
273     {
274 #ifdef RS_ENABLE_GPU
275         cout << "RS_ENABLE_GPU is true. \n";
276         cout << "Init RenderContext start. \n";
277             rc_ = RenderContextFactory::GetInstance().CreateEngine();
278             if (rc_) {
279                 cout << "Init RenderContext success.\n";
280                 rc_->InitializeEglContext();
281             } else {
282                 cout << "Init RenderContext failed, RenderContext is nullptr.\n";
283             }
284         cout << "Init RenderContext start.\n";
285 #endif
286     }
287     int screenWidth_ = 0;
288     int screenHeight_ = 0;
289 }; // class RSDisplayModeTestCase
290 } // namespace OHOS::Rosen
291 
main()292 int main()
293 {
294     RSDisplayModeTestCase::GetInstance().InitTestCase();
295     RSDisplayModeTestCase::GetInstance().TestCaseDefault();
296     return 0;
297 }
298