1 /*
2  * Copyright (c) 2024 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 "display_manager.h"
17 #include "rs_graphic_test_director.h"
18 #include "rs_parameter_parse.h"
19 #include "transaction/rs_interfaces.h"
20 #include "ui/rs_root_node.h"
21 #include "ui/rs_surface_node.h"
22 #include "ui/rs_ui_director.h"
23 
24 #include <chrono>
25 #include <condition_variable>
26 #include <mutex>
27 #include <filesystem>
28 
29 namespace OHOS {
30 namespace Rosen {
31 namespace {
32 constexpr float TOP_LEVEL_Z = 1000000.0f;
33 constexpr uint32_t SCREEN_COLOR = 0;
34 
35 class TestSurfaceCaptureCallback : public SurfaceCaptureCallback {
36 public:
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap)37     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap) override
38     {
39         {
40             std::unique_lock lock(mutex_);
41             ready_ = true;
42             pixelMap_ = pixelMap;
43         }
44         cv_.notify_all();
45 
46         if (pixelMap == nullptr) {
47             LOGE("RSGraphicTestDirector pixelMap == nullptr");
48         }
49     }
50 
Wait(int ms)51     void Wait(int ms)
52     {
53         std::unique_lock lock(mutex_);
54         cv_.wait_for(lock, std::chrono::milliseconds(ms), [&] { return ready_; });
55     }
56 
57     std::mutex mutex_;
58     std::condition_variable cv_;
59     bool ready_ = false;
60     std::shared_ptr<Media::PixelMap> pixelMap_;
61 };
62 }
63 
64 class VSyncWaiter {
65 public:
VSyncWaiter(std::shared_ptr<OHOS::AppExecFwk::EventHandler> handler,int32_t rate)66     VSyncWaiter(std::shared_ptr<OHOS::AppExecFwk::EventHandler> handler, int32_t rate)
67     {
68         frameCallback_ = {
69             .userData_ = this,
70             .callback_ = [this](int64_t, void*) { this->OnVSync(); },
71         };
72         vsyncReceiver_ = RSInterfaces::GetInstance().CreateVSyncReceiver("RSGraphicTest", handler);
73         vsyncReceiver_->Init();
74         vsyncReceiver_->SetVSyncRate(frameCallback_, rate);
75     }
76 
OnVSync()77     void OnVSync()
78     {
79         {
80             std::unique_lock lock(mutex_);
81             ++counts_;
82         }
83         cv_.notify_all();
84     }
85 
WaitForVSync(size_t count)86     void WaitForVSync(size_t count)
87     {
88         std::unique_lock lock(mutex_);
89         count += counts_;
90         cv_.wait(lock, [this, count] { return counts_ >= count; });
91     }
92 
93 private:
94     std::mutex mutex_;
95     std::condition_variable cv_;
96     size_t counts_ = 0;
97     std::shared_ptr<OHOS::Rosen::VSyncReceiver> vsyncReceiver_;
98     Rosen::VSyncReceiver::FrameCallback frameCallback_;
99 };
100 
Instance()101 RSGraphicTestDirector& RSGraphicTestDirector::Instance()
102 {
103     static RSGraphicTestDirector instance;
104     return instance;
105 }
106 
~RSGraphicTestDirector()107 RSGraphicTestDirector::~RSGraphicTestDirector()
108 {
109     rootNode_->screenSurfaceNode_->RemoveFromTree();
110     rsUiDirector_->SendMessages();
111     sleep(1);
112 }
113 
Run()114 void RSGraphicTestDirector::Run()
115 {
116     rsUiDirector_ = RSUIDirector::Create();
117     rsUiDirector_->Init();
118 
119     auto runner = OHOS::AppExecFwk::EventRunner::Create(true);
120     auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
121     rsUiDirector_->SetUITaskRunner(
122         [handler](const std::function<void()>& task, uint32_t delay) { handler->PostTask(task); });
123     runner->Run();
124 
125     screenId_ = RSInterfaces::GetInstance().GetDefaultScreenId();
126 
127     auto defaultDisplay = DisplayManager::GetInstance().GetDefaultDisplay();
128     Vector4f defaultScreenBounds = {0, 0, defaultDisplay->GetWidth(), defaultDisplay->GetHeight()};
129     screenBounds_ = defaultScreenBounds;
130 
131     rootNode_ = std::make_shared<RSGraphicRootNode>();
132     rootNode_->screenSurfaceNode_->SetBounds(defaultScreenBounds);
133     rootNode_->screenSurfaceNode_->SetFrame(defaultScreenBounds);
134     rootNode_->screenSurfaceNode_->SetBackgroundColor(SCREEN_COLOR);
135     rootNode_->screenSurfaceNode_->AttachToDisplay(screenId_);
136     rootNode_->screenSurfaceNode_->SetPositionZ(TOP_LEVEL_Z);
137 
138     rsUiDirector_->SetRSSurfaceNode(rootNode_->screenSurfaceNode_);
139     rsUiDirector_->SendMessages();
140     sleep(1);
141 
142     ResetImagePath();
143 }
144 
FlushMessage()145 void RSGraphicTestDirector::FlushMessage()
146 {
147     rsUiDirector_->SendMessages();
148 }
149 
TakeScreenCaptureAndWait(int ms)150 std::shared_ptr<Media::PixelMap> RSGraphicTestDirector::TakeScreenCaptureAndWait(int ms)
151 {
152     auto callback = std::make_shared<TestSurfaceCaptureCallback>();
153     if (!RSInterfaces::GetInstance().TakeSurfaceCapture(rootNode_->screenSurfaceNode_->GetId(), callback)) {
154         return nullptr;
155     }
156 
157     callback->Wait(ms);
158     return callback->pixelMap_;
159 }
160 
ResetImagePath()161 void RSGraphicTestDirector::ResetImagePath()
162 {
163     namespace fs = std::filesystem;
164     const auto& path = RSParameterParse::Instance().imageSavePath;
165     if (!fs::exists(path)) {
166         if (!fs::create_directories(path)) {
167             LOGE("RSGraphicTestDirector create dir failed %{public}s", path.c_str());
168         }
169     } else {
170         if (!fs::is_directory(path) || !fs::is_empty(path)) {
171             LOGE("RSGraphicTestDirector path is not dir or not empty %{public}s", path.c_str());
172         }
173     }
174 }
175 
GetRootNode() const176 std::shared_ptr<RSGraphicRootNode> RSGraphicTestDirector::GetRootNode() const
177 {
178     return rootNode_;
179 }
180 
GetScreenSize() const181 Vector2f RSGraphicTestDirector::GetScreenSize() const
182 {
183     return {screenBounds_.GetWidth(), screenBounds_.GetHeight()};
184 }
185 
SetSurfaceBounds(const Vector4f & bounds)186 void RSGraphicTestDirector::SetSurfaceBounds(const Vector4f& bounds)
187 {
188     if (rootNode_->testSurfaceNode_) {
189         rootNode_->testSurfaceNode_->SetBounds(bounds);
190     }
191 }
192 
SetSurfaceColor(const RSColor & color)193 void RSGraphicTestDirector::SetSurfaceColor(const RSColor& color)
194 {
195     if (rootNode_->testSurfaceNode_) {
196         rootNode_->testSurfaceNode_->SetBackgroundColor(color.AsRgbaInt());
197     }
198 }
199 
WaitForVSync(size_t count)200 void RSGraphicTestDirector::WaitForVSync(size_t count)
201 {
202     if (vsyncWaiter_) {
203         vsyncWaiter_->WaitForVSync(count);
204     }
205 }
206 } // namespace Rosen
207 } // namespace OHOS
208