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 Widget3DQosScoped qos("GraphicsManagerCommon::GetEngine");
132 if (viewTextures_.size() > 1u) {
133 WIDGET_LOGD("view is not unique and view size is %zu", viewTextures_.size());
134 }
135
136 auto backend = backends_.find(key);
137 if (backend == backends_.end() || backend->second == RenderBackend::UNDEFINE) {
138 WIDGET_LOGE("Get engine before register");
139 return nullptr;
140 }
141
142 if (backend->second != RenderBackend::GLES) {
143 WIDGET_LOGE("not support backend yet");
144 return nullptr;
145 }
146
147 hapInfo_ = CreateBundleName(hapInfo.hapPath_);
148
149 // gles context
150 if (engine_ == nullptr) {
151 engine_ = EngineFactory::CreateEngine(type);
152 WIDGET_LOGD("create proto engine");
153 if (!LoadEngineLib()) {
154 engine_.reset();
155 WIDGET_LOGE("load engine lib fail");
156 return nullptr;
157 }
158
159 if (!InitEngine(EGL_NO_CONTEXT, GetPlatformData(hapInfo_))) {
160 WIDGET_LOGE("init engine fail");
161 engine_.reset();
162 return nullptr;
163 }
164 } else {
165 WIDGET_LOGD("engine is initialized");
166 }
167
168 auto client = EngineFactory::CreateEngine(type);
169 client->Clone(engine_.get());
170 return client;
171 }
172
GetEngine(EngineFactory::EngineType type,int32_t key)173 std::unique_ptr<IEngine> GraphicsManagerCommon::GetEngine(EngineFactory::EngineType type, int32_t key)
174 {
175 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::GetEngine");
176 Widget3DQosScoped qos("GraphicsManagerCommon::GetEngine");
177 if (viewTextures_.size() > 1u) {
178 WIDGET_LOGD("view is not unique and view size is %zu", viewTextures_.size());
179 }
180
181 auto backend = backends_.find(key);
182 if (backend == backends_.end() || backend->second == RenderBackend::UNDEFINE) {
183 WIDGET_LOGE("Get engine before register");
184 return nullptr;
185 }
186
187 if (backend->second != RenderBackend::GLES) {
188 WIDGET_LOGE("not support backend yet");
189 return nullptr;
190 }
191
192 // gles context
193 if (engine_ == nullptr) {
194 engine_ = EngineFactory::CreateEngine(type);
195 WIDGET_LOGD("create proto engine");
196 if (!LoadEngineLib()) {
197 WIDGET_LOGE("load engine lib fail");
198 engine_.reset();
199 return nullptr;
200 }
201
202 if (!InitEngine(EGL_NO_CONTEXT, GetPlatformData())) {
203 WIDGET_LOGE("init engine fail");
204 engine_.reset();
205 return nullptr;
206 }
207 } else {
208 WIDGET_LOGD("engine is initialized");
209 }
210
211 auto client = EngineFactory::CreateEngine(type);
212 client->Clone(engine_.get());
213 return client;
214 }
215
GetOrCreateOffScreenContext(EGLContext eglContext)216 EGLContext GraphicsManagerCommon::GetOrCreateOffScreenContext(EGLContext eglContext)
217 {
218 AutoRestore scope;
219 return offScreenContextHelper_.CreateOffScreenContext(eglContext);
220 }
221
BindOffScreenContext()222 void GraphicsManagerCommon::BindOffScreenContext()
223 {
224 offScreenContextHelper_.BindOffScreenContext();
225 }
226
UnRegister(int32_t key)227 void GraphicsManagerCommon::UnRegister(int32_t key)
228 {
229 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::UnRegister");
230 WIDGET_LOGD("view unregiser %d total %zu", key, viewTextures_.size());
231
232 auto it = viewTextures_.find(key);
233 if (it == viewTextures_.end()) {
234 WIDGET_LOGE("view unregiser has not regester");
235 return;
236 }
237
238 viewTextures_.erase(it);
239 auto backend = backends_.find(key);
240 if (backend != backends_.end()) {
241 backends_.erase(backend);
242 }
243
244 if (viewTextures_.empty()) {
245 // Destroy proto engine
246 WIDGET_LOGE("view reset proto engine");
247 DeInitEngine();
248 engine_.reset();
249 }
250 // need graphics task exit!!!
251 }
252
GetRenderBackendType(int32_t key)253 RenderBackend GraphicsManagerCommon::GetRenderBackendType(int32_t key)
254 {
255 RenderBackend backend = RenderBackend::UNDEFINE;
256 auto it = backends_.find(key);
257 if (it != backends_.end()) {
258 backend = it->second;
259 }
260 return backend;
261 }
262
GetHapInfo() const263 const HapInfo& GraphicsManagerCommon::GetHapInfo() const
264 {
265 return hapInfo_;
266 }
267
HasMultiEcs()268 bool GraphicsManagerCommon::HasMultiEcs()
269 {
270 return viewTextures_.size() > 1;
271 }
272
273 #if defined(MULTI_ECS_UPDATE_AT_ONCE) && (MULTI_ECS_UPDATE_AT_ONCE == 1)
UnloadEcs(void * ecs)274 void GraphicsManagerCommon::UnloadEcs(void* ecs)
275 {
276 WIDGET_LOGD("ACE-3D GraphicsService::UnloadEcs()");
277 ecss_.erase(ecs);
278 }
279
DrawFrame(void * ecs,void * handles)280 void GraphicsManagerCommon::DrawFrame(void* ecs, void* handles)
281 {
282 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::DrawFrame");
283 ecss_[ecs] = handles;
284 WIDGET_LOGD("ACE-3D DrawFrame ecss size %zu", ecss_.size());
285 }
286
PerformDraw()287 void GraphicsManagerCommon::PerformDraw()
288 {
289 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::PerformDraw");
290 if (engine_ == nullptr) {
291 WIDGET_LOGE("ACE-3D PerformDraw but engine is null");
292 return;
293 }
294
295 WIDGET_LOGD("ACE-3D PerformDraw");
296 engine_->DrawMultiEcs(ecss_);
297 engine_->AddTextureMemoryBarrrier();
298 ecss_.clear();
299 }
300
AttachContext(const OHOS::Ace::WeakPtr<OHOS::Ace::PipelineBase> & context)301 void GraphicsManagerCommon::AttachContext(const OHOS::Ace::WeakPtr<OHOS::Ace::PipelineBase>& context)
302 {
303 WIDGET_SCOPED_TRACE("GraphicsManagerCommon::AttachContext");
304 static bool once = false;
305 if (once) {
306 return;
307 }
308
309 auto pipelineContext = context.Upgrade();
310 if (!pipelineContext) {
311 WIDGET_LOGE("ACE-3D GraphicsManagerCommon::AttachContext() GetContext failed.");
312 return;
313 }
314
315 once = true;
316 pipelineContext->SetGSVsyncCallback([&] {
317 // here we could only push sync task to graphic task, if async manner we
318 // have no chance to update the rendering future
319 PerformDraw();
320 });
321 }
322 #endif
323 } // namespace OHOS::Render3D
324