• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_graphic_test_utils.h"
19 #include "rs_trace.h"
20 #include "rs_parameter_parse.h"
21 #include "transaction/rs_interfaces.h"
22 #include "ui/rs_root_node.h"
23 #include "ui/rs_surface_node.h"
24 #include "ui/rs_ui_director.h"
25 
26 #include <chrono>
27 #include <condition_variable>
28 #include <mutex>
29 #include <filesystem>
30 
31 namespace OHOS {
32 namespace Rosen {
33 namespace {
34 constexpr float TOP_LEVEL_Z = 1000000.0f;
35 constexpr uint32_t SCREEN_COLOR = 0;
36 constexpr int64_t WAIT_ANIMATION_SYNC_TIME_OUT = 100;
37 
38 class TestSurfaceCaptureCallback : public SurfaceCaptureCallback {
39 public:
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap)40     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap) override
41     {
42         {
43             std::unique_lock lock(mutex_);
44             ready_ = true;
45             pixelMap_ = pixelMap;
46         }
47         cv_.notify_all();
48 
49         if (pixelMap == nullptr) {
50             LOGE("RSGraphicTestDirector pixelMap == nullptr");
51         }
52     }
53 
Wait(int ms)54     void Wait(int ms)
55     {
56         std::unique_lock lock(mutex_);
57         cv_.wait_for(lock, std::chrono::milliseconds(ms), [&] { return ready_; });
58     }
59 
60     std::mutex mutex_;
61     std::condition_variable cv_;
62     bool ready_ = false;
63     std::shared_ptr<Media::PixelMap> pixelMap_;
64 };
65 }
66 
67 class VSyncWaiter {
68 public:
VSyncWaiter(std::shared_ptr<OHOS::AppExecFwk::EventHandler> handler)69     explicit VSyncWaiter(std::shared_ptr<OHOS::AppExecFwk::EventHandler> handler)
70     {
71         frameCallback_ = {
72             .userData_ = this,
73             .callback_ = [this](int64_t timestamp, void*) { this->OnVSync(timestamp); },
74         };
75         vsyncReceiver_ = RSInterfaces::GetInstance().CreateVSyncReceiver("RSGraphicTest", handler);
76         vsyncReceiver_->Init();
77     }
78 
OnVSync(int64_t timestamp)79     void OnVSync(int64_t timestamp)
80     {
81         {
82             std::unique_lock lock(mutex_);
83             ready_ = true;
84             time_ = time_ + ANIMATION_VSYNC_TIME_MS * UNIT_MS_TO_NS;
85         }
86         RS_TRACE_NAME_FMT("VSyncWaiter Send OnVSync time is %llu", time_);
87         cv_.notify_all();
88     }
89 
RequestNextVSync()90     void RequestNextVSync()
91     {
92         if (vsyncReceiver_) {
93             vsyncReceiver_->RequestNextVSync(frameCallback_);
94         }
95         {
96             std::unique_lock lock(mutex_);
97             ready_ = false;
98             cv_.wait_for(lock, std::chrono::milliseconds(WAIT_ANIMATION_SYNC_TIME_OUT), [&] { return ready_; });
99         }
100         RSGraphicTestDirector::Instance().OnVSync(time_);
101     }
102 
InitStartTime()103     void InitStartTime()
104     {
105         struct timespec ts;
106         clock_gettime(CLOCK_MONOTONIC, &ts);
107         time_ = ts.tv_sec * SEC_TO_NANOSEC + ts.tv_nsec;
108     }
109 
110 private:
111     std::mutex mutex_;
112     std::condition_variable cv_;
113     bool ready_ = false;
114     int64_t time_;
115     std::shared_ptr<OHOS::Rosen::VSyncReceiver> vsyncReceiver_;
116     Rosen::VSyncReceiver::FrameCallback frameCallback_;
117 };
118 
Instance()119 RSGraphicTestDirector& RSGraphicTestDirector::Instance()
120 {
121     static RSGraphicTestDirector instance;
122     return instance;
123 }
124 
~RSGraphicTestDirector()125 RSGraphicTestDirector::~RSGraphicTestDirector()
126 {
127     rootNode_->screenSurfaceNode_->RemoveFromTree();
128     rsUiDirector_->SendMessages();
129     runner_->Stop();
130     sleep(1);
131 }
132 
Run()133 void RSGraphicTestDirector::Run()
134 {
135     rsUiDirector_ = RSUIDirector::Create();
136     rsUiDirector_->Init();
137 
138     rsUiDirector_->SetUITaskRunner([](const std::function<void()>& task, uint32_t delay) {
139         if (task) {
140             task();
141         }
142     });
143 
144     runner_ = OHOS::AppExecFwk::EventRunner::Create(true);
145     handler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner_);
146     vsyncWaiter_ = std::make_shared<VSyncWaiter>(handler_);
147     runner_->Run();
148 
149     screenId_ = RSInterfaces::GetInstance().GetDefaultScreenId();
150 
151     auto defaultDisplay = DisplayManager::GetInstance().GetDefaultDisplay();
152     Vector4f defaultScreenBounds = {0, 0, defaultDisplay->GetWidth(), defaultDisplay->GetHeight()};
153     screenBounds_ = defaultScreenBounds;
154 
155     rootNode_ = std::make_shared<RSGraphicRootNode>();
156     rootNode_->screenSurfaceNode_->SetBounds(defaultScreenBounds);
157     rootNode_->screenSurfaceNode_->SetFrame(defaultScreenBounds);
158     rootNode_->screenSurfaceNode_->SetBackgroundColor(SCREEN_COLOR);
159     rootNode_->screenSurfaceNode_->AttachToDisplay(screenId_);
160     rootNode_->screenSurfaceNode_->SetPositionZ(TOP_LEVEL_Z);
161 
162     rsUiDirector_->SetRSSurfaceNode(rootNode_->screenSurfaceNode_);
163     rsUiDirector_->SendMessages();
164     sleep(1);
165 
166     ResetImagePath();
167 }
168 
FlushMessage()169 void RSGraphicTestDirector::FlushMessage()
170 {
171     RS_TRACE_NAME("RSGraphicTestDirector::FlushMessage");
172     rsUiDirector_->SendMessages();
173 }
174 
TakeScreenCaptureAndWait(int ms)175 std::shared_ptr<Media::PixelMap> RSGraphicTestDirector::TakeScreenCaptureAndWait(int ms)
176 {
177     RS_TRACE_NAME("RSGraphicTestDirector::TakeScreenCaptureAndWait");
178     auto callback = std::make_shared<TestSurfaceCaptureCallback>();
179     if (!RSInterfaces::GetInstance().TakeSurfaceCaptureForUI(rootNode_->screenSurfaceNode_, callback)) {
180         return nullptr;
181     }
182 
183     callback->Wait(ms);
184     return callback->pixelMap_;
185 }
186 
ResetImagePath()187 void RSGraphicTestDirector::ResetImagePath()
188 {
189     namespace fs = std::filesystem;
190     const auto& path = RSParameterParse::Instance().imageSavePath;
191     if (!fs::exists(path)) {
192         if (!fs::create_directories(path)) {
193             LOGE("RSGraphicTestDirector create dir failed %{public}s", path.c_str());
194         }
195     } else {
196         if (!fs::is_directory(path) || !fs::is_empty(path)) {
197             LOGE("RSGraphicTestDirector path is not dir or not empty %{public}s", path.c_str());
198         }
199     }
200 }
201 
GetRootNode() const202 std::shared_ptr<RSGraphicRootNode> RSGraphicTestDirector::GetRootNode() const
203 {
204     return rootNode_;
205 }
206 
GetScreenSize() const207 Vector2f RSGraphicTestDirector::GetScreenSize() const
208 {
209     return {screenBounds_.GetWidth(), screenBounds_.GetHeight()};
210 }
211 
SetScreenSize(float width,float height)212 void RSGraphicTestDirector::SetScreenSize(float width, float height)
213 {
214     screenBounds_ = {0, 0, width, height};
215 }
216 
SetSingleTest(bool isSingleTest)217 void RSGraphicTestDirector::SetSingleTest(bool isSingleTest)
218 {
219     isSingleTest_ = isSingleTest;
220 }
221 
IsSingleTest()222 bool RSGraphicTestDirector::IsSingleTest()
223 {
224     return isSingleTest_;
225 }
226 
SetSurfaceBounds(const Vector4f & bounds)227 void RSGraphicTestDirector::SetSurfaceBounds(const Vector4f& bounds)
228 {
229     if (rootNode_->testSurfaceNode_) {
230         rootNode_->testSurfaceNode_->SetBounds(bounds);
231     }
232 }
233 
SetScreenSurfaceBounds(const Vector4f & bounds)234 void RSGraphicTestDirector::SetScreenSurfaceBounds(const Vector4f& bounds)
235 {
236     if (rootNode_->screenSurfaceNode_) {
237         rootNode_->screenSurfaceNode_->SetBounds(bounds);
238         rootNode_->screenSurfaceNode_->SetFrame(bounds);
239     }
240 }
241 
SetSurfaceColor(const RSColor & color)242 void RSGraphicTestDirector::SetSurfaceColor(const RSColor& color)
243 {
244     if (rootNode_->testSurfaceNode_) {
245         rootNode_->testSurfaceNode_->SetBackgroundColor(color.AsRgbaInt());
246     }
247 }
248 
StartRunUIAnimation()249 void RSGraphicTestDirector::StartRunUIAnimation()
250 {
251     if (HasUIRunningAnimation()) {
252         if (vsyncWaiter_) {
253             vsyncWaiter_->InitStartTime();
254         }
255         // request first frame
256         RequestNextVSync();
257     }
258 }
259 
HasUIRunningAnimation()260 bool RSGraphicTestDirector::HasUIRunningAnimation()
261 {
262     return rsUiDirector_->HasUIRunningAnimation();
263 }
264 
FlushAnimation(int64_t time)265 void RSGraphicTestDirector::FlushAnimation(int64_t time)
266 {
267     RS_TRACE_NAME_FMT("RSGraphicTestDirector FlushAnimation time is %llu", time);
268     rsUiDirector_->FlushAnimation(time);
269     rsUiDirector_->FlushModifier();
270 }
271 
RequestNextVSync()272 void RSGraphicTestDirector::RequestNextVSync()
273 {
274     if (vsyncWaiter_) {
275         vsyncWaiter_->RequestNextVSync();
276     }
277 }
278 
OnVSync(int64_t time)279 void RSGraphicTestDirector::OnVSync(int64_t time)
280 {
281     FlushAnimation(time);
282     //also have animation request next frame
283     if (HasUIRunningAnimation()) {
284         RequestNextVSync();
285     }
286 }
287 } // namespace Rosen
288 } // namespace OHOS
289