* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "graphics_manager_common.h"
#include "ability.h"
#include "data_ability_helper.h"
#include "napi_base_context.h"
#include "3d_widget_adapter_log.h"
#include "engine_factory.h"
#include "i_engine.h"
#include "platform_data.h"
#include "widget_trace.h"
#include "widget_qos.h"
namespace OHOS::Render3D {
HapInfo CreateBundleName(const std::string& hapPath)
{
std::shared_ptr<AbilityRuntime::ApplicationContext> context =
AbilityRuntime::ApplicationContext::GetApplicationContext();
if (!context) {
WIDGET_LOGE("Failed to get application context.");
return {};
}
auto resourceManager = context->GetResourceManager();
if (!resourceManager) {
WIDGET_LOGE("Failed to get resource manager.");
return {};
}
HapInfo hapInfo;
hapInfo.bundleName_ = resourceManager->bundleInfo.first;
hapInfo.moduleName_ = resourceManager->bundleInfo.second;
hapInfo.resourceManager_ = context->CreateModuleResourceManager(hapInfo.bundleName_, hapInfo.moduleName_);
hapInfo.hapPath_ = hapPath;
WIDGET_LOGD("bundle %s, module %s, hapPath %s",
hapInfo.bundleName_.c_str(),
hapInfo.moduleName_.c_str(),
hapInfo.hapPath_.c_str());
return hapInfo;
}
GraphicsManagerCommon::~GraphicsManagerCommon()
{
}
void GraphicsManagerCommon::Register(int32_t key, RenderBackend backend)
{
if (viewTextures_.find(key) != viewTextures_.end()) {
return;
}
viewTextures_.insert(key);
backends_[key] = backend;
return;
}
bool GraphicsManagerCommon::LoadEngineLib()
{
WIDGET_SCOPED_TRACE("GraphicsManagerCommon::LoadEngineLib");
if (engine_ == nullptr) {
return false;
}
if (engineLoaded_) {
return true;
}
auto success = engine_->LoadEngineLib();
if (success) {
engineLoaded_ = true;
}
return success;
}
bool GraphicsManagerCommon::InitEngine(EGLContext eglContext, PlatformData data)
{
WIDGET_SCOPED_TRACE("GraphicsManagerCommon::InitEngine");
if (engine_ == nullptr) {
return false;
}
if (engineInited_) {
return true;
}
auto success = engine_->InitEngine(eglContext, data);
if (success) {
engineInited_ = true;
}
return success;
}
void GraphicsManagerCommon::DeInitEngine()
{
WIDGET_SCOPED_TRACE("GraphicsManagerCommon::DeInitEngine");
if (engineInited_ && engine_ != nullptr) {
engine_->DeInitEngine();
engineInited_ = false;
}
}
void GraphicsManagerCommon::UnloadEngineLib()
{
WIDGET_SCOPED_TRACE("GraphicsManagerCommon::UnLoadEngineLib");
if (engineLoaded_ && engine_ != nullptr) {
engine_->UnloadEngineLib();
engineLoaded_ = false;
}
}
std::unique_ptr<IEngine> GraphicsManagerCommon::GetEngine(EngineFactory::EngineType type, int32_t key,
const HapInfo& hapInfo)
{
WIDGET_SCOPED_TRACE("GraphicsManagerCommon::GetEngine");
if (viewTextures_.size() > 1u) {
WIDGET_LOGD("view is not unique and view size is %zu", viewTextures_.size());
}
auto backend = backends_.find(key);
if (backend == backends_.end() || backend->second == RenderBackend::UNDEFINE) {
WIDGET_LOGE("Get engine before register");
return nullptr;
}
if (backend->second != RenderBackend::GLES) {
WIDGET_LOGE("not support backend yet");
return nullptr;
}
hapInfo_ = CreateBundleName(hapInfo.hapPath_);
if (engine_ == nullptr) {
engine_ = EngineFactory::CreateEngine(type);
WIDGET_LOGD("create proto engine");
if (!LoadEngineLib()) {
engine_.reset();
WIDGET_LOGE("load engine lib fail");
return nullptr;
}
if (!InitEngine(EGL_NO_CONTEXT, GetPlatformData(hapInfo_))) {
WIDGET_LOGE("init engine fail");
engine_.reset();
return nullptr;
}
} else {
WIDGET_LOGD("engine is initialized");
}
auto client = EngineFactory::CreateEngine(type);
client->Clone(engine_.get());
return client;
}
std::unique_ptr<IEngine> GraphicsManagerCommon::GetEngine(EngineFactory::EngineType type, int32_t key)
{
WIDGET_SCOPED_TRACE("GraphicsManagerCommon::GetEngine");
if (viewTextures_.size() > 1u) {
WIDGET_LOGD("view is not unique and view size is %zu", viewTextures_.size());
}
auto backend = backends_.find(key);
if (backend == backends_.end() || backend->second == RenderBackend::UNDEFINE) {
WIDGET_LOGE("Get engine before register");
return nullptr;
}
if (backend->second != RenderBackend::GLES) {
WIDGET_LOGE("not support backend yet");
return nullptr;
}
if (engine_ == nullptr) {
engine_ = EngineFactory::CreateEngine(type);
WIDGET_LOGD("create proto engine");
if (!LoadEngineLib()) {
WIDGET_LOGE("load engine lib fail");
engine_.reset();
return nullptr;
}
if (!InitEngine(EGL_NO_CONTEXT, GetPlatformData())) {
WIDGET_LOGE("init engine fail");
engine_.reset();
return nullptr;
}
} else {
WIDGET_LOGD("engine is initialized");
}
auto client = EngineFactory::CreateEngine(type);
client->Clone(engine_.get());
return client;
}
EGLContext GraphicsManagerCommon::GetOrCreateOffScreenContext(EGLContext eglContext)
{
AutoRestore scope;
return offScreenContextHelper_.CreateOffScreenContext(eglContext);
}
void GraphicsManagerCommon::BindOffScreenContext()
{
offScreenContextHelper_.BindOffScreenContext();
}
void GraphicsManagerCommon::UnRegister(int32_t key)
{
WIDGET_SCOPED_TRACE("GraphicsManagerCommon::UnRegister");
WIDGET_LOGD("view unregiser %d total %zu", key, viewTextures_.size());
auto it = viewTextures_.find(key);
if (it == viewTextures_.end()) {
WIDGET_LOGE("view unregiser has not regester");
return;
}
viewTextures_.erase(it);
auto backend = backends_.find(key);
if (backend != backends_.end()) {
backends_.erase(backend);
}
if (viewTextures_.empty()) {
WIDGET_LOGE("view reset proto engine");
DeInitEngine();
engine_.reset();
}
}
RenderBackend GraphicsManagerCommon::GetRenderBackendType(int32_t key)
{
RenderBackend backend = RenderBackend::UNDEFINE;
auto it = backends_.find(key);
if (it != backends_.end()) {
backend = it->second;
}
return backend;
}
const HapInfo& GraphicsManagerCommon::GetHapInfo() const
{
return hapInfo_;
}
bool GraphicsManagerCommon::HasMultiEcs()
{
return viewTextures_.size() > 1;
}
#if defined(MULTI_ECS_UPDATE_AT_ONCE) && (MULTI_ECS_UPDATE_AT_ONCE == 1)
void GraphicsManagerCommon::UnloadEcs(void* ecs)
{
WIDGET_LOGD("ACE-3D GraphicsService::UnloadEcs()");
ecss_.erase(ecs);
}
void GraphicsManagerCommon::DrawFrame(void* ecs, void* handles)
{
WIDGET_SCOPED_TRACE("GraphicsManagerCommon::DrawFrame");
ecss_[ecs] = handles;
WIDGET_LOGD("ACE-3D DrawFrame ecss size %zu", ecss_.size());
}
void GraphicsManagerCommon::PerformDraw()
{
WIDGET_SCOPED_TRACE("GraphicsManagerCommon::PerformDraw");
if (engine_ == nullptr) {
WIDGET_LOGE("ACE-3D PerformDraw but engine is null");
return;
}
WIDGET_LOGD("ACE-3D PerformDraw");
engine_->DrawMultiEcs(ecss_);
engine_->AddTextureMemoryBarrrier();
ecss_.clear();
}
void GraphicsManagerCommon::AttachContext(const OHOS::Ace::WeakPtr<OHOS::Ace::PipelineBase>& context)
{
WIDGET_SCOPED_TRACE("GraphicsManagerCommon::AttachContext");
static bool once = false;
if (once) {
return;
}
auto pipelineContext = context.Upgrade();
if (!pipelineContext) {
WIDGET_LOGE("ACE-3D GraphicsManagerCommon::AttachContext() GetContext failed.");
return;
}
once = true;
pipelineContext->SetGSVsyncCallback([&] {
PerformDraw();
});
}
#endif
}