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