1 /*
2 * Copyright (c) 2023 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 "benchmarks/rs_recording_thread.h"
17
18 #include <thread>
19 #include "common/rs_thread_handler.h"
20 #include "platform/common/rs_system_properties.h"
21 #include "platform/common/rs_log.h"
22 #include "rs_trace.h"
23 #include "transaction/rs_marshalling_helper.h"
24 #ifdef RS_ENABLE_VK
25 #include "platform/ohos/backend/rs_vulkan_context.h"
26 #endif
27
28 namespace OHOS::Rosen {
~RSRecordingThread()29 RSRecordingThread::~RSRecordingThread()
30 {
31 RS_LOGI("RSRecordingThread::~RSRecordingThread()");
32 PostTask([this]() {
33 DestroyShareEglContext();
34 });
35 }
36
Instance(RenderContext * context)37 RSRecordingThread &RSRecordingThread::Instance(RenderContext* context)
38 {
39 static RSRecordingThread instance(context);
40 return instance;
41 }
42
Start()43 void RSRecordingThread::Start()
44 {
45 runner_ = AppExecFwk::EventRunner::Create("RSRecordingThread");
46 handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
47 PostTask([this]() {
48 grContext_ = CreateShareGrContext();
49 });
50 }
51
CreateShareGrContext()52 std::shared_ptr<Drawing::GPUContext> RSRecordingThread::CreateShareGrContext()
53 {
54 RS_TRACE_NAME("CreateShareGrContext");
55 auto gpuContext = std::make_shared<Drawing::GPUContext>();
56 #ifdef RS_ENABLE_GL
57 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
58 CreateShareEglContext();
59 Drawing::GPUContextOptions options;
60 auto handler = std::make_shared<MemoryHandler>();
61 auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
62 auto size = glesVersion ? strlen(glesVersion) : 0;
63 handler->ConfigureContext(&options, glesVersion, size);
64 if (!gpuContext->BuildFromGL(options)) {
65 RS_LOGE("gpuContext is null");
66 return nullptr;
67 }
68 return gpuContext;
69 }
70 #endif
71 #ifdef RS_ENABLE_VK
72 if (RSSystemProperties::IsUseVulkan()) {
73 Drawing::GPUContextOptions options;
74 auto handler = std::make_shared<MemoryHandler>();
75 std::string vulkanVersion = RsVulkanContext::GetSingleton().GetVulkanVersion();
76 auto size = vulkanVersion.size();
77 handler->ConfigureContext(&options, vulkanVersion.c_str(), size);
78 if (!gpuContext->BuildFromVK(RsVulkanContext::GetSingleton().GetGrVkBackendContext(), options)) {
79 RS_LOGE("gpuContext is null");
80 return nullptr;
81 }
82 return gpuContext;
83 }
84 #endif
85 return nullptr;
86 }
87
CreateShareEglContext()88 void RSRecordingThread::CreateShareEglContext()
89 {
90 if (renderContext_ == nullptr) {
91 RS_LOGE("renderContext_ is nullptr");
92 return;
93 }
94 #ifdef RS_ENABLE_GL
95 if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
96 return;
97 }
98 eglShareContext_ = renderContext_->CreateShareContext();
99 if (eglShareContext_ == EGL_NO_CONTEXT) {
100 RS_LOGE("eglShareContext_ is EGL_NO_CONTEXT");
101 return;
102 }
103 if (!eglMakeCurrent(renderContext_->GetEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, eglShareContext_)) {
104 RS_LOGE("eglMakeCurrent failed");
105 return;
106 }
107 #endif
108 }
109
DestroyShareEglContext()110 void RSRecordingThread::DestroyShareEglContext()
111 {
112 #ifdef RS_ENABLE_GL
113 if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
114 return;
115 }
116 if (renderContext_ != nullptr) {
117 eglDestroyContext(renderContext_->GetEGLDisplay(), eglShareContext_);
118 eglShareContext_ = EGL_NO_CONTEXT;
119 eglMakeCurrent(renderContext_->GetEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
120 }
121 #endif
122 }
IsIdle()123 bool RSRecordingThread::IsIdle()
124 {
125 return handler_ && handler_->IsIdle();
126 }
127
PostTask(const std::function<void ()> & task)128 void RSRecordingThread::PostTask(const std::function<void()> &task)
129 {
130 if (handler_) {
131 handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
132 }
133 }
134
CheckAndRecording()135 bool RSRecordingThread::CheckAndRecording()
136 {
137 if (!handler_) {
138 Start();
139 }
140 RSTaskMessage::RSTask task = [this]() {
141 std::string line = "RSRecordingThread::CheckAndRecording curDumpFrame = " + std::to_string(curDumpFrame_) +
142 ", dumpFrameNum = " + std::to_string(dumpFrameNum_);
143 RS_LOGD("%{public}s", line.c_str());
144 mode_ = RecordingMode(RSSystemProperties::GetRecordingEnabled());
145 // init curDumpFrame
146 if (GetRecordingEnabled() && curDumpFrame_ == 0) {
147 RS_TRACE_NAME(line);
148 dumpFrameNum_ = RSSystemProperties::GetDumpFrameNum();
149 fileDir_ = RSSystemProperties::GetRecordingFile();
150 if (access(fileDir_.c_str(), F_OK) != 0) {
151 mkdir(fileDir_.c_str(), (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH));
152 }
153 }
154 };
155 PostTask(task);
156 return GetRecordingEnabled();
157 }
158
FinishRecordingOneFrameTask(RecordingMode modeSubThread)159 void RSRecordingThread::FinishRecordingOneFrameTask(RecordingMode modeSubThread)
160 {
161 for (int curFrameIndex = 0; curFrameIndex < dumpFrameNum_; curFrameIndex++) {
162 std::shared_ptr<MessageParcel> messageParcel = std::make_shared<MessageParcel>();
163 std::string opsDescription = "drawing ops no description";
164 if (modeSubThread == RecordingMode::HIGH_SPPED_RECORDING) {
165 RS_LOGI("RSRecordingThread::High speed!");
166 messageParcel->SetMaxCapacity(RECORDING_PARCEL_CAPCITY);
167 RSMarshallingHelper::BeginNoSharedMem(std::this_thread::get_id());
168 RSMarshallingHelper::Marshalling(*messageParcel, drawCmdListVec_[curFrameIndex]);
169 RSMarshallingHelper::EndNoSharedMem();
170 } else if (modeSubThread == RecordingMode::LOW_SPEED_RECORDING) {
171 messageParcel = messageParcelVec_[curFrameIndex];
172 }
173 OHOS::Rosen::Benchmarks::WriteMessageParcelToFile(messageParcel, opsDescription, curFrameIndex, fileDir_);
174 }
175 drawCmdListVec_.clear();
176 messageParcelVec_.clear();
177 opsDescriptionVec_.clear();
178 curDumpFrame_ = 0;
179 dumpFrameNum_ = 0;
180 fileDir_ = "";
181 RSSystemProperties::SetRecordingDisenabled();
182 RS_LOGD("RSRecordingThread::FinishRecordingOneFrame isRecordingEnabled = false");
183 }
184
FinishRecordingOneFrame()185 void RSRecordingThread::FinishRecordingOneFrame()
186 {
187 std::string line = "RSRecordingThread::FinishRecordingOneFrame curDumpFrame = " + std::to_string(curDumpFrame_) +
188 ", dumpFrameNum = " + std::to_string(dumpFrameNum_);
189 RS_LOGD("%{public}s", line.c_str());
190 RS_TRACE_NAME(line);
191 if (curDumpFrame_ < dumpFrameNum_) {
192 curDumpFrame_++;
193 return;
194 }
195 auto modeSubThread = mode_;
196 mode_ = RecordingMode::STOP_RECORDING;
197 #ifdef RS_ENABLE_GL
198 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
199 RSTaskMessage::RSTask task = [this, modeSubThread]() {
200 FinishRecordingOneFrameTask(modeSubThread);
201 };
202 PostTask(task);
203 } else {
204 FinishRecordingOneFrameTask(modeSubThread);
205 }
206 #else
207 FinishRecordingOneFrameTask(modeSubThread);
208 #endif
209 }
210
RecordingToFile(const std::shared_ptr<Drawing::DrawCmdList> & drawCmdList)211 void RSRecordingThread::RecordingToFile(const std::shared_ptr<Drawing::DrawCmdList>& drawCmdList)
212 {
213 if (curDumpFrame_ < 0 || drawCmdList == nullptr) {
214 return;
215 }
216 if (mode_ == RecordingMode::HIGH_SPPED_RECORDING) {
217 drawCmdListVec_.push_back(drawCmdList);
218 } else if (mode_ == RecordingMode::LOW_SPEED_RECORDING) {
219 std::shared_ptr<MessageParcel> messageParcel = std::make_shared<MessageParcel>();
220 messageParcel->SetMaxCapacity(RECORDING_PARCEL_CAPCITY);
221 RSMarshallingHelper::BeginNoSharedMem(std::this_thread::get_id());
222 RSMarshallingHelper::Marshalling(*messageParcel, drawCmdList);
223 RSMarshallingHelper::EndNoSharedMem();
224 opsDescriptionVec_.push_back(drawCmdList->GetOpsWithDesc());
225 messageParcelVec_.push_back(messageParcel);
226 }
227
228 FinishRecordingOneFrame();
229 }
230 }
231