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 "common/rs_background_thread.h"
17 #include "platform/common/rs_log.h"
18 #include "platform/common/rs_system_properties.h"
19 #if defined(RS_ENABLE_UNI_RENDER)
20 #ifdef RS_ENABLE_GL
21 #include "render_context/render_context.h"
22 #endif
23 #ifdef RS_ENABLE_VK
24 #include "platform/ohos/backend/rs_vulkan_context.h"
25 #endif
26 #endif
27 #include "rs_trace.h"
28
29 #ifdef RES_BASE_SCHED_ENABLE
30 #include "qos.h"
31 #endif
32
33 namespace OHOS::Rosen {
Instance()34 RSBackgroundThread& RSBackgroundThread::Instance()
35 {
36 static RSBackgroundThread instance;
37 return instance;
38 }
39
RSBackgroundThread()40 RSBackgroundThread::RSBackgroundThread()
41 {
42 runner_ = AppExecFwk::EventRunner::Create("RSBackgroundThread");
43 handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
44 #ifdef RES_BASE_SCHED_ENABLE
45 PostTask([this]() {
46 auto ret = OHOS::QOS::SetThreadQos(OHOS::QOS::QosLevel::QOS_USER_INTERACTIVE);
47 RS_LOGI("RSBackgroundThread: SetThreadQos retcode = %{public}d", ret);
48 });
49 #endif
50 }
51
PostTask(const std::function<void ()> & task)52 void RSBackgroundThread::PostTask(const std::function<void()>& task)
53 {
54 if (handler_) {
55 handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
56 }
57 }
58
PostSyncTask(const std::function<void ()> & task)59 void RSBackgroundThread::PostSyncTask(const std::function<void()>& task)
60 {
61 if (handler_) {
62 handler_->PostSyncTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
63 }
64 }
65
66 #if defined(RS_ENABLE_UNI_RENDER) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
67 #ifdef RS_ENABLE_GL
CreateShareEglContext()68 void RSBackgroundThread::CreateShareEglContext()
69 {
70 if (RSSystemProperties::IsUseVulkan()) {
71 return;
72 }
73 if (renderContext_ == nullptr) {
74 RS_LOGE("renderContext_ is nullptr.");
75 return;
76 }
77 eglShareContext_ = renderContext_->CreateShareContext();
78 if (eglShareContext_ == EGL_NO_CONTEXT) {
79 RS_LOGE("eglShareContext_ is EGL_NO_CONTEXT");
80 return;
81 }
82 if (!eglMakeCurrent(renderContext_->GetEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, eglShareContext_)) {
83 RS_LOGE("eglMakeCurrent failed.");
84 return;
85 }
86 }
87 #endif
InitRenderContext(RenderContext * context)88 void RSBackgroundThread::InitRenderContext(RenderContext* context)
89 {
90 renderContext_ = context;
91 PostTask([this]() {
92 gpuContext_ = CreateShareGPUContext();
93 if (gpuContext_ == nullptr) {
94 return;
95 }
96 gpuContext_->RegisterPostFunc([](const std::function<void()>& task) {
97 RSBackgroundThread::Instance().PostTask(task);
98 });
99 });
100 }
101
GetShareGPUContext() const102 std::shared_ptr<Drawing::GPUContext> RSBackgroundThread::GetShareGPUContext() const
103 {
104 return gpuContext_;
105 }
106
CreateShareGPUContext()107 std::shared_ptr<Drawing::GPUContext> RSBackgroundThread::CreateShareGPUContext()
108 {
109 RS_TRACE_NAME("CreateShareGrContext");
110 #ifdef RS_ENABLE_GL
111 if (!RSSystemProperties::IsUseVulkan()) {
112 auto gpuContext = std::make_shared<Drawing::GPUContext>();
113 if (gpuContext == nullptr) {
114 return nullptr;
115 }
116 CreateShareEglContext();
117
118 Drawing::GPUContextOptions options = {};
119 auto handler = std::make_shared<MemoryHandler>();
120 auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
121 auto size = glesVersion ? strlen(glesVersion) : 0;
122 handler->ConfigureContext(&options, glesVersion, size);
123 if (!gpuContext->BuildFromGL(options)) {
124 RS_LOGE("BuildFromGL fail");
125 return nullptr;
126 }
127 return gpuContext;
128 }
129 #endif
130
131 #ifdef RS_ENABLE_VK
132 if (RSSystemProperties::IsUseVulkan()) {
133 auto gpuContext = RsVulkanContext::GetSingleton().CreateDrawingContext();
134 if (gpuContext == nullptr) {
135 RS_LOGE("BuildFromVK fail");
136 return nullptr;
137 }
138 return gpuContext;
139 }
140 #endif
141 return nullptr;
142 }
143
CleanGrResource()144 void RSBackgroundThread::CleanGrResource()
145 {
146 PostTask([this]() {
147 RS_TRACE_NAME("ResetGPUContext release resource");
148 if (gpuContext_ == nullptr) {
149 RS_LOGE("RSBackgroundThread::gpuContext_ is nullptr");
150 return;
151 }
152 gpuContext_->FreeGpuResources();
153 RS_LOGD("RSBackgroundThread::CleanGrResource() finished");
154 });
155 }
156 #endif
157 }
158