• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
52 #ifndef USE_ROSEN_DRAWING
53 #ifdef NEW_SKIA
CreateShareGrContext()54 sk_sp<GrDirectContext> RSRecordingThread::CreateShareGrContext()
55 #else
56 sk_sp<GrContext> RSRecordingThread::CreateShareGrContext()
57 #endif
58 {
59     RS_TRACE_NAME("RSRecordingThread::CreateShareGrContext");
60 #ifdef RS_ENABLE_GL
61     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
62         CreateShareEglContext();
63         const GrGLInterface *grGlInterface = GrGLCreateNativeInterface();
64         sk_sp<const GrGLInterface> glInterface(grGlInterface);
65         if (glInterface.get() == nullptr) {
66             RS_LOGE("CreateShareGrContext failed");
67             return nullptr;
68         }
69 
70         GrContextOptions options = {};
71         options.fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
72         // fix svg antialiasing bug
73         options.fGpuPathRenderers &= ~GpuPathRenderers::kAtlas;
74         options.fPreferExternalImagesOverES3 = true;
75         options.fDisableDistanceFieldPaths = true;
76 
77         auto handler = std::make_shared<MemoryHandler>();
78         auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
79         auto size = glesVersion ? strlen(glesVersion) : 0;
80         handler->ConfigureContext(&options, glesVersion, size);
81 
82 #ifdef NEW_SKIA
83         sk_sp<GrDirectContext> grContext = GrDirectContext::MakeGL(std::move(glInterface), options);
84 #else
85         sk_sp<GrContext> grContext = GrContext::MakeGL(std::move(glInterface), options);
86 #endif
87         if (grContext == nullptr) {
88             RS_LOGE("nullptr grContext is null");
89             return nullptr;
90         }
91         return grContext;
92     }
93 #endif
94 
95 #ifdef RS_ENABLE_VK
96     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
97         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
98         sk_sp<GrDirectContext> grContext = GrDirectContext::MakeVulkan(
99             RsVulkanContext::GetSingleton().GetGrVkBackendContext());
100         if (grContext == nullptr) {
101             RS_LOGE("nullptr grContext is null");
102             return nullptr;
103         }
104         return grContext;
105     }
106 #endif
107     return nullptr;
108 }
109 #else
CreateShareGrContext()110 std::shared_ptr<Drawing::GPUContext> RSRecordingThread::CreateShareGrContext()
111 {
112     RS_TRACE_NAME("CreateShareGrContext");
113     auto gpuContext = std::make_shared<Drawing::GPUContext>();
114 #ifdef RS_ENABLE_GL
115     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
116         CreateShareEglContext();
117         Drawing::GPUContextOptions options;
118         auto handler = std::make_shared<MemoryHandler>();
119         auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
120         auto size = glesVersion ? strlen(glesVersion) : 0;
121         handler->ConfigureContext(&options, glesVersion, size);
122         if (!gpuContext->BuildFromGL(options)) {
123             RS_LOGE("nullptr gpuContext is null");
124             return nullptr;
125         }
126         return gpuContext;
127     }
128 #endif
129 #ifdef RS_ENABLE_VK
130     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
131         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
132         Drawing::GPUContextOptions options;
133         auto handler = std::make_shared<MemoryHandler>();
134         std::string vulkanVersion = RsVulkanContext::GetSingleton().GetVulkanVersion();
135         auto size = vulkanVersion.size();
136         handler->ConfigureContext(&options, vulkanVersion.c_str(), size);
137         if (!gpuContext->BuildFromVK(RsVulkanContext::GetSingleton().GetGrVkBackendContext(), options)) {
138             RS_LOGE("nullptr gpuContext is null");
139             return nullptr;
140         }
141         return gpuContext;
142     }
143 #endif
144     return nullptr;
145 }
146 #endif
147 
CreateShareEglContext()148 void RSRecordingThread::CreateShareEglContext()
149 {
150     if (renderContext_ == nullptr) {
151         RS_LOGE("renderContext_ is nullptr");
152         return;
153     }
154 #ifdef RS_ENABLE_GL
155     if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
156         return;
157     }
158     eglShareContext_ = renderContext_->CreateShareContext();
159     if (eglShareContext_ == EGL_NO_CONTEXT) {
160         RS_LOGE("eglShareContext_ is EGL_NO_CONTEXT");
161         return;
162     }
163     if (!eglMakeCurrent(renderContext_->GetEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, eglShareContext_)) {
164         RS_LOGE("eglMakeCurrent failed");
165         return;
166     }
167 #endif
168 }
169 
DestroyShareEglContext()170 void RSRecordingThread::DestroyShareEglContext()
171 {
172 #ifdef RS_ENABLE_GL
173     if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
174         return;
175     }
176     if (renderContext_ != nullptr) {
177         eglDestroyContext(renderContext_->GetEGLDisplay(), eglShareContext_);
178         eglShareContext_ = EGL_NO_CONTEXT;
179         eglMakeCurrent(renderContext_->GetEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
180     }
181 #endif
182 }
IsIdle()183 bool RSRecordingThread::IsIdle()
184 {
185     return handler_ && handler_->IsIdle();
186 }
187 
PostTask(const std::function<void ()> & task)188 void RSRecordingThread::PostTask(const std::function<void()> &task)
189 {
190     if (handler_) {
191         handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
192     }
193 }
194 
CheckAndRecording()195 bool RSRecordingThread::CheckAndRecording()
196 {
197     if (!handler_) {
198         Start();
199     }
200     RSTaskMessage::RSTask task = [this]() {
201         std::string line = "RSRecordingThread::CheckAndRecording curDumpFrame = " + std::to_string(curDumpFrame_) +
202             ", dumpFrameNum = " + std::to_string(dumpFrameNum_);
203         RS_LOGD("%{public}s", line.c_str());
204         mode_ = RecordingMode(RSSystemProperties::GetRecordingEnabled());
205         // init curDumpFrame
206         if (GetRecordingEnabled() && curDumpFrame_ == 0) {
207             RS_TRACE_NAME(line);
208             dumpFrameNum_ = RSSystemProperties::GetDumpFrameNum();
209             fileDir_ = RSSystemProperties::GetRecordingFile();
210             if (access(fileDir_.c_str(), F_OK) != 0) {
211                 mkdir(fileDir_.c_str(), (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH));
212             }
213         }
214     };
215     PostTask(task);
216     return GetRecordingEnabled();
217 }
218 
FinishRecordingOneFrameTask(RecordingMode modeSubThread)219 void RSRecordingThread::FinishRecordingOneFrameTask(RecordingMode modeSubThread)
220 {
221     for (int curFrameIndex = 0; curFrameIndex < dumpFrameNum_; curFrameIndex++) {
222         std::shared_ptr<MessageParcel> messageParcel = std::make_shared<MessageParcel>();
223         std::string opsDescription = "drawing ops no description";
224         if (modeSubThread == RecordingMode::HIGH_SPPED_RECORDING) {
225             RS_LOGI("RSRecordingThread::High speed!");
226             messageParcel->SetMaxCapacity(RECORDING_PARCEL_CAPCITY);
227             RSMarshallingHelper::BeginNoSharedMem(std::this_thread::get_id());
228 #ifndef USE_ROSEN_DRAWING
229             drawCmdListVec_[curFrameIndex]->Marshalling(*messageParcel);
230 #else
231             RSMarshallingHelper::Marshalling(*messageParcel, drawCmdListVec_[curFrameIndex]);
232 #endif
233             RSMarshallingHelper::EndNoSharedMem();
234             opsDescription = drawCmdListVec_[curFrameIndex]-> GetOpsWithDesc();
235         } else if (modeSubThread == RecordingMode::LOW_SPEED_RECORDING) {
236             messageParcel = messageParcelVec_[curFrameIndex];
237             opsDescription = opsDescriptionVec_[curFrameIndex];
238         }
239         OHOS::Rosen::Benchmarks::WriteMessageParcelToFile(messageParcel, opsDescription, curFrameIndex, fileDir_);
240     }
241     drawCmdListVec_.clear();
242     messageParcelVec_.clear();
243     opsDescriptionVec_.clear();
244     curDumpFrame_ = 0;
245     dumpFrameNum_ = 0;
246     fileDir_ = "";
247     RSSystemProperties::SetRecordingDisenabled();
248     RS_LOGD("RSRecordingThread::FinishRecordingOneFrame isRecordingEnabled = false");
249 }
250 
FinishRecordingOneFrame()251 void RSRecordingThread::FinishRecordingOneFrame()
252 {
253     std::string line = "RSRecordingThread::FinishRecordingOneFrame curDumpFrame = " + std::to_string(curDumpFrame_) +
254         ", dumpFrameNum = " + std::to_string(dumpFrameNum_);
255     RS_LOGD("%{public}s", line.c_str());
256     RS_TRACE_NAME(line);
257     if (curDumpFrame_ < dumpFrameNum_) {
258         curDumpFrame_++;
259         return;
260     }
261     auto modeSubThread = mode_;
262     mode_ = RecordingMode::STOP_RECORDING;
263 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
264     RSTaskMessage::RSTask task = [this, modeSubThread]() {
265         FinishRecordingOneFrameTask(modeSubThread);
266     };
267     PostTask(task);
268 #else
269     FinishRecordingOneFrameTask(modeSubThread);
270 #endif
271 }
272 
273 #ifndef USE_ROSEN_DRAWING
RecordingToFile(const std::shared_ptr<DrawCmdList> & drawCmdList)274 void RSRecordingThread::RecordingToFile(const std::shared_ptr<DrawCmdList>& drawCmdList)
275 #else
276 void RSRecordingThread::RecordingToFile(const std::shared_ptr<Drawing::DrawCmdList>& drawCmdList)
277 #endif
278 {
279     if (curDumpFrame_ < 0) {
280         return;
281     }
282     if (mode_ == RecordingMode::HIGH_SPPED_RECORDING) {
283         drawCmdListVec_.push_back(drawCmdList);
284     } else if (mode_ == RecordingMode::LOW_SPEED_RECORDING) {
285 #ifndef USE_ROSEN_DRAWING
286         std::shared_ptr<MessageParcel> messageParcel = std::make_shared<MessageParcel>();
287         messageParcel->SetMaxCapacity(RECORDING_PARCEL_CAPCITY);
288         RSMarshallingHelper::BeginNoSharedMem(std::this_thread::get_id());
289         drawCmdList->Marshalling(*messageParcel);
290         RSMarshallingHelper::EndNoSharedMem();
291         opsDescriptionVec_.push_back(drawCmdList->GetOpsWithDesc());
292         messageParcelVec_.push_back(messageParcel);
293 #else
294         std::shared_ptr<MessageParcel> messageParcel = std::make_shared<MessageParcel>();
295         messageParcel->SetMaxCapacity(RECORDING_PARCEL_CAPCITY);
296         RSMarshallingHelper::BeginNoSharedMem(std::this_thread::get_id());
297         RSMarshallingHelper::Marshalling(*messageParcel, drawCmdList);
298         RSMarshallingHelper::EndNoSharedMem();
299         opsDescriptionVec_.push_back(drawCmdList->GetOpsWithDesc());
300         messageParcelVec_.push_back(messageParcel);
301 #endif
302     }
303 
304     FinishRecordingOneFrame();
305 }
306 }
307