1 /*
2 * Copyright (c) 2024 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 "graphics_manager_common.h"
17
18 #include "ability.h"
19 #include "data_ability_helper.h"
20 #include "napi_base_context.h"
21
22 #include "3d_widget_adapter_log.h"
23 #include "engine_factory.h"
24 #include "i_engine.h"
25 #include "platform_data.h"
26 #include "widget_trace.h"
27 #include "widget_qos.h"
28
29 namespace OHOS::Render3D {
CreateBundleName(const std::string & hapPath)30 HapInfo CreateBundleName(const std::string& hapPath)
31 {
32 std::shared_ptr<AbilityRuntime::ApplicationContext> context =
33 AbilityRuntime::ApplicationContext::GetApplicationContext();
34 if (!context) {
35 WIDGET_LOGE("Failed to get application context.");
36 return {};
37 }
38 auto resourceManager = context->GetResourceManager();
39 if (!resourceManager) {
40 WIDGET_LOGE("Failed to get resource manager.");
41 return {};
42 }
43 HapInfo hapInfo;
44 hapInfo.bundleName_ = resourceManager->bundleInfo.first;
45 hapInfo.moduleName_ = resourceManager->bundleInfo.second;
46 hapInfo.resourceManager_ = context->CreateModuleResourceManager(hapInfo.bundleName_, hapInfo.moduleName_);
47 hapInfo.hapPath_ = hapPath;
48 WIDGET_LOGD("bundle %s, module %s, hapPath %s",
49 hapInfo.bundleName_.c_str(),
50 hapInfo.moduleName_.c_str(),
51 hapInfo.hapPath_.c_str());
52 return hapInfo;
53 }
54
~GraphicsManagerCommon()55 GraphicsManagerCommon::~GraphicsManagerCommon()
56 {
57 // should never be called
58 }
59
Register(int32_t key,RenderBackend backend)60 void GraphicsManagerCommon::Register(int32_t key, RenderBackend backend)
61 {
62 if (viewTextures_.find(key) != viewTextures_.end()) {
63 return;
64 }
65
66 viewTextures_.insert(key);
67 backends_[key] = backend;
68 return;
69 }
70
LoadEngineLib()71 bool GraphicsManagerCommon::LoadEngineLib()
72 {
73 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::LoadEngineLib");
74 if (engine_ == nullptr) {
75 return false;
76 }
77
78 if (engineLoaded_) {
79 return true;
80 }
81
82 auto success = engine_->LoadEngineLib();
83 if (success) {
84 engineLoaded_ = true;
85 }
86
87 return success;
88 }
89
InitEngine(EGLContext eglContext,PlatformData data)90 bool GraphicsManagerCommon::InitEngine(EGLContext eglContext, PlatformData data)
91 {
92 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::InitEngine");
93 if (engine_ == nullptr) {
94 return false;
95 }
96
97 if (engineInited_) {
98 return true;
99 }
100
101 auto success = engine_->InitEngine(eglContext, data);
102 if (success) {
103 engineInited_ = true;
104 }
105
106 return success;
107 }
108
DeInitEngine()109 void GraphicsManagerCommon::DeInitEngine()
110 {
111 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::DeInitEngine");
112 if (engineInited_ && engine_ != nullptr) {
113 engine_->DeInitEngine();
114 engineInited_ = false;
115 }
116 }
117
UnloadEngineLib()118 void GraphicsManagerCommon::UnloadEngineLib()
119 {
120 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::UnLoadEngineLib");
121 if (engineLoaded_ && engine_ != nullptr) {
122 engine_->UnloadEngineLib();
123 engineLoaded_ = false;
124 }
125 }
126
GetEngine(EngineFactory::EngineType type,int32_t key,const HapInfo & hapInfo)127 std::unique_ptr<IEngine> GraphicsManagerCommon::GetEngine(EngineFactory::EngineType type, int32_t key,
128 const HapInfo& hapInfo)
129 {
130 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::GetEngine");
131 if (viewTextures_.size() > 1u) {
132 WIDGET_LOGD("view is not unique and view size is %zu", viewTextures_.size());
133 }
134
135 auto backend = backends_.find(key);
136 if (backend == backends_.end() || backend->second == RenderBackend::UNDEFINE) {
137 WIDGET_LOGE("Get engine before register");
138 return nullptr;
139 }
140
141 if (backend->second != RenderBackend::GLES) {
142 WIDGET_LOGE("not support backend yet");
143 return nullptr;
144 }
145
146 hapInfo_ = CreateBundleName(hapInfo.hapPath_);
147
148 // gles context
149 if (engine_ == nullptr) {
150 engine_ = EngineFactory::CreateEngine(type);
151 WIDGET_LOGD("create proto engine");
152 if (!LoadEngineLib()) {
153 engine_.reset();
154 WIDGET_LOGE("load engine lib fail");
155 return nullptr;
156 }
157
158 if (!InitEngine(EGL_NO_CONTEXT, GetPlatformData(hapInfo_))) {
159 WIDGET_LOGE("init engine fail");
160 engine_.reset();
161 return nullptr;
162 }
163 } else {
164 WIDGET_LOGD("engine is initialized");
165 }
166
167 auto client = EngineFactory::CreateEngine(type);
168 client->Clone(engine_.get());
169 return client;
170 }
171
GetEngine(EngineFactory::EngineType type,int32_t key)172 std::unique_ptr<IEngine> GraphicsManagerCommon::GetEngine(EngineFactory::EngineType type, int32_t key)
173 {
174 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::GetEngine");
175 if (viewTextures_.size() > 1u) {
176 WIDGET_LOGD("view is not unique and view size is %zu", viewTextures_.size());
177 }
178
179 auto backend = backends_.find(key);
180 if (backend == backends_.end() || backend->second == RenderBackend::UNDEFINE) {
181 WIDGET_LOGE("Get engine before register");
182 return nullptr;
183 }
184
185 if (backend->second != RenderBackend::GLES) {
186 WIDGET_LOGE("not support backend yet");
187 return nullptr;
188 }
189
190 // gles context
191 if (engine_ == nullptr) {
192 engine_ = EngineFactory::CreateEngine(type);
193 WIDGET_LOGD("create proto engine");
194 if (!LoadEngineLib()) {
195 WIDGET_LOGE("load engine lib fail");
196 engine_.reset();
197 return nullptr;
198 }
199
200 if (!InitEngine(EGL_NO_CONTEXT, GetPlatformData())) {
201 WIDGET_LOGE("init engine fail");
202 engine_.reset();
203 return nullptr;
204 }
205 } else {
206 WIDGET_LOGD("engine is initialized");
207 }
208
209 auto client = EngineFactory::CreateEngine(type);
210 client->Clone(engine_.get());
211 return client;
212 }
213
GetOrCreateOffScreenContext(EGLContext eglContext)214 EGLContext GraphicsManagerCommon::GetOrCreateOffScreenContext(EGLContext eglContext)
215 {
216 AutoRestore scope;
217 return offScreenContextHelper_.CreateOffScreenContext(eglContext);
218 }
219
BindOffScreenContext()220 void GraphicsManagerCommon::BindOffScreenContext()
221 {
222 offScreenContextHelper_.BindOffScreenContext();
223 }
224
UnRegister(int32_t key)225 void GraphicsManagerCommon::UnRegister(int32_t key)
226 {
227 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::UnRegister");
228 WIDGET_LOGD("view unregiser %d total %zu", key, viewTextures_.size());
229
230 auto it = viewTextures_.find(key);
231 if (it == viewTextures_.end()) {
232 WIDGET_LOGE("view unregiser has not regester");
233 return;
234 }
235
236 viewTextures_.erase(it);
237 auto backend = backends_.find(key);
238 if (backend != backends_.end()) {
239 backends_.erase(backend);
240 }
241
242 if (viewTextures_.empty()) {
243 // Destroy proto engine
244 WIDGET_LOGE("view reset proto engine");
245 DeInitEngine();
246 engine_.reset();
247 }
248 // need graphics task exit!!!
249 }
250
GetRenderBackendType(int32_t key)251 RenderBackend GraphicsManagerCommon::GetRenderBackendType(int32_t key)
252 {
253 RenderBackend backend = RenderBackend::UNDEFINE;
254 auto it = backends_.find(key);
255 if (it != backends_.end()) {
256 backend = it->second;
257 }
258 return backend;
259 }
260
GetHapInfo() const261 const HapInfo& GraphicsManagerCommon::GetHapInfo() const
262 {
263 return hapInfo_;
264 }
265
HasMultiEcs()266 bool GraphicsManagerCommon::HasMultiEcs()
267 {
268 return viewTextures_.size() > 1;
269 }
270
271 #if defined(MULTI_ECS_UPDATE_AT_ONCE) && (MULTI_ECS_UPDATE_AT_ONCE == 1)
UnloadEcs(void * ecs)272 void GraphicsManagerCommon::UnloadEcs(void* ecs)
273 {
274 WIDGET_LOGD("ACE-3D GraphicsService::UnloadEcs()");
275 ecss_.erase(ecs);
276 }
277
DrawFrame(void * ecs,void * handles)278 void GraphicsManagerCommon::DrawFrame(void* ecs, void* handles)
279 {
280 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::DrawFrame");
281 ecss_[ecs] = handles;
282 WIDGET_LOGD("ACE-3D DrawFrame ecss size %zu", ecss_.size());
283 }
284
PerformDraw()285 void GraphicsManagerCommon::PerformDraw()
286 {
287 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::PerformDraw");
288 if (engine_ == nullptr) {
289 WIDGET_LOGE("ACE-3D PerformDraw but engine is null");
290 return;
291 }
292
293 WIDGET_LOGD("ACE-3D PerformDraw");
294 engine_->DrawMultiEcs(ecss_);
295 engine_->AddTextureMemoryBarrrier();
296 ecss_.clear();
297 }
298
AttachContext(const OHOS::Ace::WeakPtr<OHOS::Ace::PipelineBase> & context)299 void GraphicsManagerCommon::AttachContext(const OHOS::Ace::WeakPtr<OHOS::Ace::PipelineBase>& context)
300 {
301 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::AttachContext");
302 static bool once = false;
303 if (once) {
304 return;
305 }
306
307 auto pipelineContext = context.Upgrade();
308 if (!pipelineContext) {
309 WIDGET_LOGE("ACE-3D GraphicsManagerCommon::AttachContext() GetContext failed.");
310 return;
311 }
312
313 once = true;
314 pipelineContext->SetGSVsyncCallback([&] {
315 // here we could only push sync task to graphic task, if async manner we
316 // have no chance to update the rendering future
317 PerformDraw();
318 });
319 }
320 #endif
321 } // namespace OHOS::Render3D
322