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 namespace OHOS::Rosen {
Instance()30 RSBackgroundThread& RSBackgroundThread::Instance()
31 {
32 static RSBackgroundThread instance;
33 return instance;
34 }
35
RSBackgroundThread()36 RSBackgroundThread::RSBackgroundThread()
37 {
38 runner_ = AppExecFwk::EventRunner::Create("RSBackgroundThread");
39 handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
40 }
41
PostTask(const std::function<void ()> & task)42 void RSBackgroundThread::PostTask(const std::function<void()>& task)
43 {
44 if (handler_) {
45 handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
46 }
47 }
48 #if defined(RS_ENABLE_UNI_RENDER) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
49 #ifdef RS_ENABLE_GL
CreateShareEglContext()50 void RSBackgroundThread::CreateShareEglContext()
51 {
52 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
53 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
54 return;
55 }
56 if (renderContext_ == nullptr) {
57 RS_LOGE("renderContext_ is nullptr.");
58 return;
59 }
60 eglShareContext_ = renderContext_->CreateShareContext();
61 if (eglShareContext_ == EGL_NO_CONTEXT) {
62 RS_LOGE("eglShareContext_ is EGL_NO_CONTEXT");
63 return;
64 }
65 if (!eglMakeCurrent(renderContext_->GetEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, eglShareContext_)) {
66 RS_LOGE("eglMakeCurrent failed.");
67 return;
68 }
69 }
70 #endif
71 #ifndef USE_ROSEN_DRAWING
InitRenderContext(RenderContext * context)72 void RSBackgroundThread::InitRenderContext(RenderContext* context)
73 {
74 renderContext_ = context;
75 PostTask([this]() {
76 grContext_ = CreateShareGrContext();
77 });
78 }
79
GetShareGrContext() const80 sk_sp<GrDirectContext> RSBackgroundThread::GetShareGrContext() const
81 {
82 return grContext_;
83 }
84
CreateShareGrContext()85 sk_sp<GrDirectContext> RSBackgroundThread::CreateShareGrContext()
86 {
87 RS_TRACE_NAME("CreateShareGrContext");
88 #ifdef RS_ENABLE_GL
89 if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
90 RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
91 CreateShareEglContext();
92 const GrGLInterface* glGlInterface = GrGLCreateNativeInterface();
93 sk_sp<const GrGLInterface> glInterface(glGlInterface);
94 if (glInterface.get() == nullptr) {
95 RS_LOGE("GrGLCreateNativeInterface failed.");
96 return nullptr;
97 }
98
99 GrContextOptions options = {};
100 options.fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
101 // fix svg antialiasing bug
102 options.fGpuPathRenderers &= ~GpuPathRenderers::kAtlas;
103 options.fPreferExternalImagesOverES3 = true;
104 options.fDisableDistanceFieldPaths = true;
105
106 auto handler = std::make_shared<MemoryHandler>();
107 auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
108 auto size = glesVersion ? strlen(glesVersion) : 0;
109 /* /data/service/el0/render_service is shader cache dir*/
110 handler->ConfigureContext(&options, glesVersion, size, "/data/service/el0/render_service", true);
111
112 sk_sp<GrDirectContext> grContext = GrDirectContext::MakeGL(std::move(glInterface), options);
113 if (grContext == nullptr) {
114 RS_LOGE("nullptr grContext is null");
115 return nullptr;
116 }
117 return grContext;
118 }
119 #endif
120
121 #ifdef RS_ENABLE_VK
122 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
123 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
124 sk_sp<GrDirectContext> grContext = RsVulkanContext::GetSingleton().CreateSkContext();
125 if (grContext == nullptr) {
126 RS_LOGE("nullptr grContext is null");
127 return nullptr;
128 }
129 return grContext;
130 }
131 #endif
132 return nullptr;
133 }
134
CleanGrResource()135 void RSBackgroundThread::CleanGrResource()
136 {
137 PostTask([this]() {
138 RS_TRACE_NAME("ResetGrContext release resource");
139 if (grContext_ == nullptr) {
140 RS_LOGE("RSBackgroundThread::grContext_ is nullptr");
141 return;
142 }
143 grContext_->freeGpuResources();
144 RS_LOGD("RSBackgroundThread::CleanGrResource() finished");
145 });
146 }
147 #else
InitRenderContext(RenderContext * context)148 void RSBackgroundThread::InitRenderContext(RenderContext* context)
149 {
150 renderContext_ = context;
151 PostTask([this]() {
152 gpuContext_ = CreateShareGPUContext();
153 });
154 }
155
GetShareGPUContext() const156 std::shared_ptr<Drawing::GPUContext> RSBackgroundThread::GetShareGPUContext() const
157 {
158 return gpuContext_;
159 }
160
CreateShareGPUContext()161 std::shared_ptr<Drawing::GPUContext> RSBackgroundThread::CreateShareGPUContext()
162 {
163 RS_TRACE_NAME("CreateShareGrContext");
164 #ifdef RS_ENABLE_GL
165 if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
166 RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
167 auto gpuContext = std::make_shared<Drawing::GPUContext>();
168 if (gpuContext == nullptr) {
169 RS_LOGE("BuildFromVK fail");
170 return nullptr;
171 }
172 CreateShareEglContext();
173
174 Drawing::GPUContextOptions options = {};
175 auto handler = std::make_shared<MemoryHandler>();
176 auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
177 auto size = glesVersion ? strlen(glesVersion) : 0;
178 handler->ConfigureContext(&options, glesVersion, size);
179 if (!gpuContext->BuildFromGL(options)) {
180 RS_LOGE("BuildFromGL fail");
181 return nullptr;
182 }
183 return gpuContext;
184 }
185 #endif
186
187 #ifdef RS_ENABLE_VK
188 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
189 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
190 auto gpuContext = RsVulkanContext::GetSingleton().CreateDrawingContext();
191 if (gpuContext == nullptr) {
192 RS_LOGE("BuildFromVK fail");
193 return nullptr;
194 }
195 return gpuContext;
196 }
197 #endif
198 return nullptr;
199 }
200
CleanGrResource()201 void RSBackgroundThread::CleanGrResource()
202 {
203 PostTask([this]() {
204 RS_TRACE_NAME("ResetGPUContext release resource");
205 if (gpuContext_ == nullptr) {
206 RS_LOGE("RSBackgroundThread::gpuContext_ is nullptr");
207 return;
208 }
209 gpuContext_->FreeGpuResources();
210 RS_LOGD("RSBackgroundThread::CleanGrResource() finished");
211 });
212 }
213 #endif
214 #endif
215 }
216