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