完成多例实现

This commit is contained in:
JackLee 2026-04-03 16:58:37 +08:00
parent 58a39f0ac9
commit 4a72555468
16 changed files with 450 additions and 425 deletions

View File

@ -39,9 +39,11 @@ endforeach()
add_library(opencax SHARED
napi_init.cpp
# Header
NativeEGLOCCT/EGLCore.h
NativeEGLOCCT/NativeRender.h
NativeEGLOCCT/NativeRenderThread.h
NativeEGLOCCT/EGLMgr/EGLCore.h
NativeEGLOCCT/EGLMgr/EGLSubCore.h
NativeEGLOCCT/OCCTMgr/OCCTMgr.h
NativeEGLOCCT/OCCTMgr/Render.h
NativeEGLOCCT/OCCTMgr/RenderThread.h
NativeEGLOCCT/NativeMgr.h
NativeEGLOCCT/V3d/V3dOGD/V3dOGD.h
NativeEGLOCCT/V3d/V3dViewer/V3dViewer.h
@ -54,9 +56,11 @@ add_library(opencax SHARED
NativeEGLOCCT/V3d/V3dTri/V3dWCSTri.h
NativeEGLOCCT/V3d/V3dTri/V3dTriCube.h
# Cpp Src
NativeEGLOCCT/EGLCore.cpp
NativeEGLOCCT/NativeRender.cpp
NativeEGLOCCT/NativeRenderThread.cpp
NativeEGLOCCT/EGLMgr/EGLCore.cpp
NativeEGLOCCT/EGLMgr/EGLSubCore.cpp
NativeEGLOCCT/OCCTMgr/OCCTMgr.cpp
NativeEGLOCCT/OCCTMgr/Render.cpp
NativeEGLOCCT/OCCTMgr/RenderThread.cpp
NativeEGLOCCT/NativeMgr.cpp
NativeEGLOCCT/V3d/V3dOGD/V3dOGD.cpp
NativeEGLOCCT/V3d/V3dViewer/V3dViewer.cpp
@ -67,7 +71,9 @@ add_library(opencax SHARED
NativeEGLOCCT/V3d/V3dDrawer/V3dDrawer.cpp
NativeEGLOCCT/V3d/V3dTri/V3dTri.cpp
NativeEGLOCCT/V3d/V3dTri/V3dWCSTri.cpp
NativeEGLOCCT/V3d/V3dTri/V3dTriCube.cpp)
NativeEGLOCCT/V3d/V3dTri/V3dTriCube.cpp
)
#
find_library(EGL-lib EGL)

View File

@ -1,246 +0,0 @@
#include "EGLCore.h"
#include <cstdio>
#include "NativeEGLOCCT/common.h"
#ifndef NATIVE_TAG
#define NATIVE_TAG "EGLCore"
#endif
namespace NativeOpenCAX {
// 配置EGL
EGLint cfgAttribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 0,
EGL_NONE
};
// 创建EGL context
EGLint ctxAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
EGLCore::EGLCore():
eglDisplay(EGL_NO_DISPLAY),
eglConfig(nullptr)
{
}
EGLCore::~EGLCore() {
destroy();
}
bool EGLCore::InitEglCtx(OHNativeWindow* nativeWin, std::string id) {
if (!nativeWin || id.empty()) {
HILOG_ERROR(NATIVE_TAG, "nativeWin is null or id is empty");
return false;
}
EGLint err;
const EGLint maxConfigSize = 1;
EGLint numConfigs;
EGLSurface nSur = EGL_NO_SURFACE;
EGLContext nCtx = EGL_NO_CONTEXT;
if (eglCtx.empty()&&eglSur.empty()&&eglWin.empty()) {
eglMainId=id;
eglCrtId = id;
eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (eglDisplay == EGL_NO_DISPLAY) {
HILOG_ERROR(NATIVE_TAG, "EGLDisplay is invalid, err: 0x%x", eglGetError());
return false;
}
if (!eglInitialize(eglDisplay, nullptr, nullptr)) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "Main Ctx EGL Init Failed: 0x%x", err);
eglDisplay = EGL_NO_DISPLAY;
return false;
}
HILOG_INFO(NATIVE_TAG, "EGLDisplay init success");
if (!eglChooseConfig(eglDisplay, cfgAttribs, &eglConfig, maxConfigSize, &numConfigs) || numConfigs == 0) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "Main EGL ChooseConfig failed, err: 0x%x", err);
eglTerminate(eglDisplay);
eglDisplay = EGL_NO_DISPLAY;
eglConfig = nullptr;
return false;
}
nSur = eglCreateWindowSurface(eglDisplay, eglConfig, (NativeWindowType)nativeWin, nullptr);
if (nSur == EGL_NO_SURFACE) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "Main EGL SURFACE Init Failed, err: 0x%x", err);
eglTerminate(eglDisplay);
eglDisplay = EGL_NO_DISPLAY;
eglConfig = nullptr;
return false;
}
nCtx = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, ctxAttribs);
if (nCtx == EGL_NO_CONTEXT) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "Main EGL Context Init Failed, err: 0x%x", err);
eglDestroySurface(eglDisplay, nSur);
eglTerminate(eglDisplay);
eglDisplay = EGL_NO_DISPLAY;
eglConfig = nullptr;
return false;
}
} else {
eglCrtId = id;
if (eglDisplay == EGL_NO_DISPLAY || eglConfig == nullptr || eglCtx.find(eglMainId) == eglCtx.end()) {
HILOG_ERROR(NATIVE_TAG, "Main EGL context not initialized, can't create sub context");
return false;
}
// 新增校验主Context是否为有效状态
EGLContext mainCtx = eglCtx[eglMainId];
EGLBoolean isMainCtxValid = eglQueryContext(eglDisplay, mainCtx, EGL_CONTEXT_CLIENT_VERSION, nullptr);
if (isMainCtxValid == EGL_FALSE) {
HILOG_ERROR(NATIVE_TAG, "Main EGL context is invalid, err: 0x%x", eglGetError());
return false;
}
nSur = eglCreateWindowSurface(eglDisplay, eglConfig, (NativeWindowType)nativeWin, nullptr);
if (nSur == EGL_NO_SURFACE) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "Sub EGL SURFACE Init Failed, err: 0x%x", err);
return false;
}
nCtx = eglCreateContext(eglDisplay, eglConfig, eglCtx[eglMainId], ctxAttribs);
if (nCtx == EGL_NO_CONTEXT) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "Sub EGL Context Init Failed, err: 0x%x", err);
eglDestroySurface(eglDisplay, nSur);
return false;
}
}
if (!eglMakeCurrent(eglDisplay, nSur, nSur, nCtx)) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "eglMakeCurrent failed after create, err: 0x%x", err);
eglDestroyContext(eglDisplay, nCtx);
eglDestroySurface(eglDisplay, nSur);
return false;
}
GLenum glError = glGetError();
if (glError != GL_NO_ERROR) {
HILOG_ERROR(NATIVE_TAG, "GL error after init: %d", glError);
eglDestroyContext(eglDisplay, nCtx);
eglDestroySurface(eglDisplay, nSur);
return false;
}
eglWin[id] = nativeWin;
eglSur[id] = nSur;
eglCtx[id] = nCtx;
return true;
}
// 切换上下文
void EGLCore::makeCurrent() {
std::lock_guard<std::mutex> lock(crtMutex);
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
// 校验资源是否存在
auto surIt = eglSur.find(eglCrtId);
auto ctxIt = eglCtx.find(eglCrtId);
if (surIt == eglSur.end() || ctxIt == eglCtx.end()) {
HILOG_ERROR(NATIVE_TAG, "No surface/context for id: %s", eglCrtId.c_str());
return;
}
if (!eglMakeCurrent(eglDisplay, surIt->second, surIt->second, ctxIt->second)) {
EGLint err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "eglMakeCurrent failed: 0x%x, id: %s", err, eglCrtId.c_str());
}
}
// 交换缓冲区
bool EGLCore::swapBuffers() {
std::lock_guard<std::mutex> lock(swapMutex);
auto surIt = eglSur.find(eglCrtId);
if (surIt == eglSur.end() || surIt->second == EGL_NO_SURFACE) {
HILOG_ERROR(NATIVE_TAG, "No valid surface for id: %s", eglCrtId.c_str());
return false;
}
bool ret = eglSwapBuffers(eglDisplay, surIt->second);
if (!ret) {
EGLint err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "eglSwapBuffers failed: 0x%{public}x, id: %{public}s", err, eglCrtId.c_str());
}
return ret;
}
// 销毁指定id的资源
void EGLCore::destroy() {
if (eglDisplay == EGL_NO_DISPLAY) {
return;
}
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
// 销毁上下文
auto ctxIt = eglCtx.find(eglCrtId);
if (ctxIt != eglCtx.end() && ctxIt->second != EGL_NO_CONTEXT) {
eglDestroyContext(eglDisplay, ctxIt->second);
eglCtx.erase(ctxIt);
}
// 销毁Surface
auto surIt = eglSur.find(eglCrtId);
if (surIt != eglSur.end() && surIt->second != EGL_NO_SURFACE) {
eglDestroySurface(eglDisplay, surIt->second);
eglSur.erase(surIt);
}
// 移除Window映射不销毁Window由外部管理
eglWin.erase(eglCrtId);
HILOG_INFO(NATIVE_TAG, "Destroy EGL resources for id: %s", eglCrtId.c_str());
if(eglCrtId==eglMainId){
eglTerminate(eglDisplay);
eglDisplay = EGL_NO_DISPLAY;
eglConfig = nullptr;
eglCrtId = "";
eglMainId= "";
}
}
std::string EGLCore::GetCurrentXCompId() {
return eglCrtId;
}
EGLSurface EGLCore::GetSurface() {
auto it = eglSur.find(eglCrtId);
return (it != eglSur.end()) ? it->second : EGL_NO_SURFACE;
}
EGLContext EGLCore::GetContext() {
auto it = eglCtx.find(eglCrtId);
return (it != eglCtx.end()) ? it->second : EGL_NO_CONTEXT;
}
EGLDisplay EGLCore::GetDisplay() {
return eglDisplay;
}
EGLConfig EGLCore::GetConfig() {
return eglConfig;
}
OHNativeWindow* EGLCore::GetOHNativeWindow() {
auto it = eglWin.find(eglCrtId);
return (it != eglWin.end()) ? it->second : nullptr;
}
} // namespace NativeOpenCAX

View File

@ -1,56 +0,0 @@
/*
* Copyright (c) 2025 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.
*/
#ifndef EGLMGR_H
#define EGLMGR_H
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <map>
#include <iostream>
#include <native_window/external_window.h>
namespace NativeOpenCAX {
enum EGL_TYPE{
EGL_MAIN,
EGL_SUB
};
class EGLCore {
public:
EGLCore();
~EGLCore();
bool InitEglCtx(OHNativeWindow* window,std::string id);
std::string GetCurrentXCompId();
void makeCurrent();
bool swapBuffers();
void destroy();
EGLSurface GetSurface();
EGLContext GetContext();
EGLDisplay GetDisplay();
EGLConfig GetConfig();
OHNativeWindow* GetOHNativeWindow();
private:
std::mutex crtMutex;
std::mutex swapMutex;
std::string eglCrtId;
std::string eglMainId;
EGLDisplay eglDisplay;
EGLConfig eglConfig;
std::unordered_map<std::string, EGLContext> eglCtx;
std::unordered_map<std::string, EGLSurface> eglSur;
std::unordered_map<std::string, OHNativeWindow*> eglWin;
};
} // namespace NativeOpenCAX
#endif // EGLCORE_H

View File

@ -0,0 +1,72 @@
//
// Created on 2026/4/3.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".
#include "EGLCore.h"
#ifndef NATIVE_TAG
#define NATIVE_TAG "EGLCore"
#endif
namespace NativeOpenCAX {
// 配置EGL
EGLint cfgAttribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 0,
EGL_NONE
};
EGLCore::EGLCore():eglDisplay(EGL_NO_DISPLAY),eglConfig(nullptr)
{
}
EGLCore::~EGLCore(){
eglTerminate(eglDisplay);
eglDisplay = EGL_NO_DISPLAY;
eglConfig = nullptr;
}
bool EGLCore::InitEGLDisplay(){
EGLint err;
const EGLint maxConfigSize = 1;
EGLint numConfigs;
eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (eglDisplay == EGL_NO_DISPLAY) {
HILOG_ERROR(NATIVE_TAG, "EGLDisplay is invalid, err: 0x%x", eglGetError());
return false;
}
if (!eglInitialize(eglDisplay, nullptr, nullptr)) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "Main Ctx EGL Init Failed: 0x%x", err);
eglDisplay = EGL_NO_DISPLAY;
return false;
}
HILOG_INFO(NATIVE_TAG, "EGLDisplay init success");
if (!eglChooseConfig(eglDisplay, cfgAttribs, &eglConfig, maxConfigSize, &numConfigs) || numConfigs == 0) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "Main EGL ChooseConfig failed, err: 0x%x", err);
eglTerminate(eglDisplay);
eglDisplay = EGL_NO_DISPLAY;
eglConfig = nullptr;
return false;
}
HILOG_INFO(NATIVE_TAG, "EGLDisplayConfig init success");
return true;
}
EGLDisplay EGLCore::GetEGLDisplay(){
return eglDisplay;
}
EGLConfig EGLCore::GetEGLConfig(){
return eglConfig;
}
}

View File

@ -0,0 +1,26 @@
//
// Created on 2026/4/3.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".
#ifndef OPENCAX_EGLCORE_H
#define OPENCAX_EGLCORE_H
#include "../common.h"
#include <EGL/egl.h>
namespace NativeOpenCAX {
class EGLCore {
public:
EGLCore();
~EGLCore();
bool InitEGLDisplay();
EGLDisplay GetEGLDisplay();
EGLConfig GetEGLConfig();
private:
EGLDisplay eglDisplay;
EGLConfig eglConfig;
};
} // namespace NativeOpenCAX
#endif //OPENCAX_EGLCORE_H

View File

@ -0,0 +1,85 @@
//
// Created on 2026/4/3.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".
#include "EGLSubCore.h"
#ifndef NATIVE_TAG
#define NATIVE_TAG "EGLSubCore"
#endif
namespace NativeOpenCAX {
// 创建EGL context
EGLint ctxAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
EGLSubCore::EGLSubCore() : eglSur(EGL_NO_SURFACE), eglCtx(EGL_NO_CONTEXT), eglWin(nullptr) {}
EGLSubCore::~EGLSubCore() {}
bool EGLSubCore::InitEGLSubCore(EGLDisplay _display, EGLConfig _config, OHNativeWindow *_win) {
EGLint err;
eglWin=_win;
eglSur = eglCreateWindowSurface(_display, _config, (NativeWindowType)_win, nullptr);
if (eglSur == EGL_NO_SURFACE) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "Main EGL SURFACE Init Failed, err: 0x%x", err);
return false;
}
eglCtx = eglCreateContext(_display, _config, EGL_NO_CONTEXT, ctxAttribs);
if (eglCtx == EGL_NO_CONTEXT) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "Main EGL Context Init Failed, err: 0x%x", err);
return false;
}
if (!eglMakeCurrent(_display, eglSur, eglSur, eglCtx)) {
err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "eglMakeCurrent failed after create, err: 0x%x", err);
eglDestroyContext(_display, eglCtx);
eglDestroySurface(_display, eglSur);
return false;
}
GLenum glError = glGetError();
if (glError != GL_NO_ERROR) {
HILOG_ERROR(NATIVE_TAG, "GL error after init: %d", glError);
eglDestroyContext(_display, eglCtx);
eglDestroySurface(_display, eglSur);
return false;
}
HILOG_INFO(NATIVE_TAG, "EGLSubCore init success");
return true;
}
void EGLSubCore::makeCurrent(EGLDisplay eglDisplay) {
if (!eglMakeCurrent(eglDisplay, eglSur, eglSur, eglCtx)) {
EGLint err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "eglMakeCurrent failed: 0x%x", err);
}
}
// 交换缓冲区
bool EGLSubCore::swapBuffers(EGLDisplay eglDisplay) {
bool ret = eglSwapBuffers(eglDisplay, eglSur);
if (!ret) {
EGLint err = eglGetError();
HILOG_ERROR(NATIVE_TAG, "eglSwapBuffers failed: 0x%{public}x", err);
}
return ret;
}
void EGLSubCore::destroy(EGLDisplay eglDisplay) {
if (eglDisplay == EGL_NO_DISPLAY) {
return;
}
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
// 销毁上下文
eglDestroyContext(eglDisplay, eglCtx);
// 销毁Surface
eglDestroySurface(eglDisplay, eglSur);
HILOG_INFO(NATIVE_TAG, "Destroy EGL resources");
}
OHNativeWindow* EGLSubCore::GetWindow(){
return eglWin;
}
} // namespace NativeOpenCAX

View File

@ -0,0 +1,33 @@
//
// Created on 2026/4/3.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".
#ifndef OPENCAX_EGLSUBCORE_H
#define OPENCAX_EGLSUBCORE_H
#include "../common.h"
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <native_window/external_window.h>
namespace NativeOpenCAX {
class EGLSubCore {
public:
EGLSubCore();
~EGLSubCore();
bool InitEGLSubCore(EGLDisplay _display,EGLConfig _config,OHNativeWindow* _win);
void makeCurrent(EGLDisplay eglDisplay);
bool swapBuffers(EGLDisplay eglDisplay);
void destroy(EGLDisplay eglDisplay);
OHNativeWindow* GetWindow();
public:
EGLContext eglCtx;
EGLSurface eglSur;
OHNativeWindow* eglWin;
};
}
#endif //OPENCAX_EGLSUBCORE_H

View File

@ -27,16 +27,16 @@ std::unordered_map<std::string, ArkUI_NodeHandle> NativeMgr::nodeHandleMap_;
std::unordered_map<void *, OH_ArkUI_SurfaceCallback *> NativeMgr::callbackMap_;
ArkUI_NativeNodeAPI_1 *nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1"));
// [StartExclude plugin_manager_cpp]
NativeMgr NativeMgr::pluginManager_;
OH_NativeXComponent_Callback NativeMgr::xSurfaceTouchEventCallBack;
OH_NativeXComponent_MouseEvent_Callback NativeMgr::xMouseEventCallBack;
std::string NativeMgr::crtXCompId;
NativeMgr NativeMgr::pluginManager_;
OCCTMgr OCCTMgr::occtMgr;
std::unordered_map<std::string,NXInfo*> NativeMgr::NxInfos;
int32_t NativeMgr::hasDraw_ = 0;
int32_t NativeMgr::hasChangeColor_ = 0;
static std::map<std::string, std::shared_ptr<NativeRenderThread>> rdThreads;
static std::mutex mapMutex;
std::string uuid_v4() {
@ -63,11 +63,7 @@ NativeMgr::~NativeMgr() {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "~NativeMgr");
nativeXComponentMap_.clear();
std::lock_guard<std::mutex> lock(mapMutex);
if (rdThreads.find(crtXCompId) != rdThreads.end()) {
rdThreads[crtXCompId]->stop();
rdThreads.erase(crtXCompId);
}
OCCTMgr::GetInstance()->destroy(crtXCompId);
for (auto iter = pluginManagerMap_.begin(); iter != pluginManagerMap_.end(); ++iter) {
if (iter->second != nullptr) {
delete iter->second;
@ -143,22 +139,17 @@ void NativeMgr::OnSurfaceCreated(OH_NativeXComponent *component, void *window) {
OH_NativeXComponent_GetXComponentSize(component, window, &bfWidth, &bfHeight);
std::lock_guard<std::mutex> lock(mapMutex);
if (rdThreads.find(crtXCompId) == rdThreads.end()) {
auto renderThread = std::make_shared<NativeRenderThread>();
if(!OCCTMgr::GetInstance()->findRenderThread(crtXCompId)){
HILOG_ERROR(NATIVE_TAG,"uint64_t bfSize:%{public}dX%{public}d",bfWidth,bfHeight);
rdThreads[crtXCompId] = renderThread;
//renderThread->InitRender(crtXCompId,bfWidth, bfHeight,reinterpret_cast<OHNativeWindow*>(window));
//renderThread->start();
OCCTMgr::GetInstance()->initOCCTMgr();
}
OCCTMgr::GetInstance()->createReaderThread(crtXCompId, bfWidth, bfHeight, reinterpret_cast<OHNativeWindow*>(window));
}
void NativeMgr::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceDestroyed");
{
std::lock_guard<std::mutex> lock(mapMutex);
if (rdThreads.find(crtXCompId) != rdThreads.end()) {
rdThreads[crtXCompId]->stop();
rdThreads.erase(crtXCompId);
}
OCCTMgr::GetInstance()->destroy(crtXCompId);
}
}
void NativeMgr::OnSurfaceChanged(OH_NativeXComponent *component, void *window) {
@ -168,11 +159,14 @@ void NativeMgr::OnSurfaceChanged(OH_NativeXComponent *component, void *window) {
return;
}
std::lock_guard<std::mutex> lock(mapMutex);
if (rdThreads.find(crtXCompId) != rdThreads.end()) {
if (OCCTMgr::GetInstance()->findRenderThread(crtXCompId)) {
HILOG_ERROR(NATIVE_TAG,"uint64_t Size:%{public}dX%{public}d",bfWidth,bfHeight);
bfWidth=afWidth;
bfHeight=afHeight;
rdThreads[crtXCompId]->resizeWindow(bfWidth, bfHeight);
auto renderThread=OCCTMgr::GetInstance()->getRenderThread(crtXCompId);
if(renderThread!=nullptr){
renderThread->resizeWindow(bfWidth, bfHeight);
}
}
}
}
@ -206,12 +200,12 @@ void NativeMgr::OnMouseEvent(OH_NativeXComponent *comp, void *win) {
return;
}
NativeMgr::timestamp=mouseEvent.timestamp;
auto it = rdThreads.find(crtXCompId);
if (it == rdThreads.end()) {
auto renderThread=OCCTMgr::GetInstance()->getRenderThread(crtXCompId);
if(renderThread==nullptr){
HILOG_WARN(NATIVE_TAG, "Render thread not found for rotation.");
return;
}
auto renderThread = it->second;
float curtX,curtY;
//开发测试模拟器输出鼠标按钮和时间类型,时间戳
bool _log=true;
@ -495,8 +489,12 @@ napi_value NativeMgr::NapiLoadModel(napi_env env, napi_callback_info info) {
std::string path = value2String(env, args[0]);
{
std::lock_guard<std::mutex> lock(mapMutex);
if (rdThreads.find(crtXCompId) != rdThreads.end()) {
rdThreads[crtXCompId]->loadModel(std::string(path));
auto renderThread=OCCTMgr::GetInstance()->getRenderThread(crtXCompId);
if(renderThread==nullptr){
HILOG_WARN(NATIVE_TAG, "Render thread not found for rotation.");
}else{
renderThread->loadModel(std::string(path));
}
}
return nullptr;
@ -510,8 +508,11 @@ napi_value NativeMgr::SwitchView(napi_env env, napi_callback_info info){
std::string viewName = value2String(env, args[0]);
{
std::lock_guard<std::mutex> lock(mapMutex);
if (rdThreads.find(crtXCompId) != rdThreads.end()) {
rdThreads[crtXCompId]->swicthView(viewName);
auto renderThread=OCCTMgr::GetInstance()->getRenderThread(crtXCompId);
if(renderThread==nullptr){
HILOG_WARN(NATIVE_TAG, "Render thread not found for rotation.");
}else{
renderThread->swicthView(viewName);
}
}
return nullptr;

View File

@ -22,10 +22,9 @@
#include <napi/native_api.h>
#include <string>
#include <unordered_map>
#include "EGLCore.h"
#include "arkui/native_node.h"
#include "arkui/native_node_napi.h"
#include "NativeRenderThread.h"
#include "OCCTMgr/OCCTMgr.h"
#include "arkui/ui_input_event.h"
#include <multimodalinput/oh_input_manager.h>
@ -81,6 +80,7 @@ public:
void OnMouseEvent(OH_NativeXComponent *component, void *window);
private:
static NativeMgr pluginManager_;
//static OCCTMgr occtMgr;
std::unordered_map<std::string, OH_NativeXComponent*> nativeXComponentMap_;
std::unordered_map<std::string, NativeMgr*> pluginManagerMap_;
public:

View File

@ -0,0 +1,69 @@
//
// Created on 2026/4/3.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".
#include "OCCTMgr.h"
#ifndef NATIVE_TAG
#define NATIVE_TAG "OCCTMgr"
#endif
namespace NativeOpenCAX {
OCCTMgr::OCCTMgr():eglCore(nullptr)
{
}
OCCTMgr::~OCCTMgr(){
}
//第一次创建需要初始化EGLDisplay
void OCCTMgr::initOCCTMgr(){
if(!eglCore){
eglCore=new EGLCore();
}
if(!eglCore->InitEGLDisplay()){
HILOG_ERROR(NATIVE_TAG, "OCCTMgr EGLCore Init Failed");
}
}
void OCCTMgr::createReaderThread(std::string _id,int width,int height,OHNativeWindow *_win){
ThreadInfo thrInfo;
thrInfo.width=width;
thrInfo.height=height;
thrInfo.win=_win;
thrInfo.eglCore=eglCore;
auto _rdThread = new RenderThread;
_rdThread->InitRender(thrInfo);
_rdThread->start();
rdThreadMgr[_id]=_rdThread;
}
bool OCCTMgr::findRenderThread(std::string id){
if (rdThreadMgr.find(id) != rdThreadMgr.end()) {
return true;
}
return false;
}
void OCCTMgr::destroy(std::string id) {
if(findRenderThread(id)){
rdThreadMgr[id]->stop();
delete rdThreadMgr[id];
rdThreadMgr[id]=nullptr;
rdThreadMgr.erase(id);
}
}
bool OCCTMgr::checkEGLCore(){
if(eglCore!=nullptr){
return true;
}
return false;
}
RenderThread* OCCTMgr::getRenderThread(std::string id){
auto _renderThread=rdThreadMgr[id];
if(_renderThread!=nullptr){
return _renderThread;
}
return nullptr;
}
}

View File

@ -0,0 +1,38 @@
//
// Created on 2026/4/3.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".
#ifndef OPENCAX_OCCTMGR_H
#define OPENCAX_OCCTMGR_H
#include <unordered_map>
#include "../common.h"
#include "../EGLMgr/EGLCore.h"
#include "../EGLMgr/EGLSubCore.h"
#include "RenderThread.h"
namespace NativeOpenCAX {
class OCCTMgr {
public:
OCCTMgr();
~OCCTMgr();
static OCCTMgr* GetInstance() {
return &OCCTMgr::occtMgr;
}
void initOCCTMgr();
void createReaderThread(std::string _id,int width,int height,OHNativeWindow *_win);
bool checkEGLCore();
bool findRenderThread(std::string);
void destroy(std::string id);
RenderThread* getRenderThread(std::string);
private:
static OCCTMgr occtMgr;
std::string currentId;
EGLCore* eglCore;
std::unordered_map<std::string,RenderThread*> rdThreadMgr;
};
}
#endif //OPENCAX_OCCTMGR_H

View File

@ -1,16 +1,16 @@
#include "NativeRender.h"
#include "Render.h"
#include "Aspect_TypeOfLine.hxx"
#include "Font_FontAspect.hxx"
#include "STEPControl_Reader.hxx"
#ifndef NATIVE_TAG
#define NATIVE_TAG "NativeRender"
#define NATIVE_TAG "Render"
#endif
static std::mutex renderMutex;
namespace NativeOpenCAX {
NativeRender::NativeRender(int w, int h):
Render::Render(int w, int h):
width(0),
height(0),
v3dTri(new V3dTri),
@ -27,9 +27,9 @@ v3dwin(new V3dWin)
height = h;
}
NativeRender::~NativeRender() { shapes_.clear(); }
Render::~Render() { shapes_.clear(); }
bool NativeRender::init(EGLDisplay eglDisp,EGLContext ctx,EGLConfig eglConfig) {
bool Render::init(EGLDisplay eglDisp,EGLContext ctx,EGLConfig eglConfig) {
//初始化OpenGL
if (!v3dogd->InitV3dOGD(eglDisp,ctx,eglConfig)) {
HILOG_ERROR(NATIVE_TAG, "Init GraphicDriver Fail!");
@ -79,7 +79,7 @@ bool NativeRender::init(EGLDisplay eglDisp,EGLContext ctx,EGLConfig eglConfig) {
return true;
}
bool NativeRender::loadModel(const std::string &filePath) {
bool Render::loadModel(const std::string &filePath) {
// 清除现有模型
for (auto &shape : shapes_) {
v3dctx->ctx->Remove(shape, false);
@ -134,12 +134,12 @@ bool NativeRender::loadModel(const std::string &filePath) {
}
// setTranslation
void NativeRender::setTranslation(float tx, float ty) {
void Render::setTranslation(float tx, float ty) {
v3dTri->SetTranslationX(tx);
v3dTri->SetTranslationY(ty);
}
void NativeRender::render() {
void Render::render() {
if (v3dview->view.IsNull()) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Render", "View Is Null");
return;
@ -148,22 +148,22 @@ void NativeRender::render() {
v3dview->Redraw();
}
void NativeRender::resize(int w, int h) {
void Render::resize(int w, int h) {
HILOG_ERROR(NATIVE_TAG, "InPut Size:%{public}d,%{public}d", w, h);
v3dwin->Resize(w, h);
}
void NativeRender::setRotation(float xAngle, float yAngle) { v3dcr->SetRotation(xAngle, yAngle); }
void Render::setRotation(float xAngle, float yAngle) { v3dcr->SetRotation(xAngle, yAngle); }
void NativeRender::setZoomLevel(float zoom) {
void Render::setZoomLevel(float zoom) {
v3dTri->SetZoomLevel(std::max(0.1f, std::min(zoom, 5.0f))); // 限制缩放范围
}
void NativeRender::setClearColor(float r, float g, float b, float a) { v3dview->SetClearColor(r, g, b, a); }
void NativeRender::resetView() { v3dview->ResetView(); }
void NativeRender::SwitchView(std::string str) {
void Render::setClearColor(float r, float g, float b, float a) { v3dview->SetClearColor(r, g, b, a); }
void Render::resetView() { v3dview->ResetView(); }
void Render::SwitchView(std::string str) {
v3dview->SwitchView(str);
}
void NativeRender::InitDevText(){
void Render::InitDevText(){
Handle(AIS_TextLabel) aTextLabel = new AIS_TextLabel();
const char16_t chinese_array[] = u"新时代社会主义中国接班人";
aTextLabel->SetText(chinese_array);

View File

@ -6,8 +6,7 @@
#include "AIS_Shape.hxx"
#include "common.h"
#include "EGLCore.h"
#include "../common.h"
#include <Standard_Handle.hxx>
#include <gp_Trsf.hxx>
#include <gp_EulerSequence.hxx>
@ -15,22 +14,22 @@
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include "V3d/V3dTri/V3dTri.h"
#include "V3d/V3dTri/V3dTriCube.h"
#include "V3d/V3dCa/V3dCa.h"
#include "V3d/V3dCtx/V3dCtx.h"
#include "V3d/V3dOGD/V3dOGD.h"
#include "V3d/V3dWin/V3dWin.h"
#include "V3d/V3dView/V3dView.h"
#include "V3d/V3dViewer/V3dViewer.h"
#include "../V3d/V3dTri/V3dTri.h"
#include "../V3d/V3dTri/V3dTriCube.h"
#include "../V3d/V3dCa/V3dCa.h"
#include "../V3d/V3dCtx/V3dCtx.h"
#include "../V3d/V3dOGD/V3dOGD.h"
#include "../V3d/V3dWin/V3dWin.h"
#include "../V3d/V3dView/V3dView.h"
#include "../V3d/V3dViewer/V3dViewer.h"
//TextLabel_Dev
#include <AIS_TextLabel.hxx>
namespace NativeOpenCAX {
class NativeRender {
class Render {
public:
NativeRender(int width, int height);
~NativeRender();
Render(int width, int height);
~Render();
bool init(EGLDisplay eglDisp,EGLContext ctx,EGLConfig eglConfig);
bool loadModel(const std::string& filePath);

View File

@ -1,4 +1,4 @@
#include "NativeRenderThread.h"
#include "RenderThread.h"
#include "Font_FontAspect.hxx"
#include "NativeEGLOCCT/common.h"
#include <cstdio>
@ -6,37 +6,32 @@
#include <hilog/log.h>
namespace NativeOpenCAX {
NativeRenderThread::NativeRenderThread()
: isRunning_(false),
EGLCoreMgr(nullptr),
RenderCoreMgr(std::map<std::string,NativeRender*>())
RenderThread::RenderThread()
: isRunning_(false)
{
}
NativeRenderThread::~NativeRenderThread() {
RenderThread::~RenderThread() {
stop();
}
void NativeRenderThread::InitRender(std::string id,int _width,int _height,OHNativeWindow* win){
void RenderThread::InitRender(ThreadInfo _thrInfo){
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "renderLoop","Thread ID: %{public}d",std::this_thread::get_id());
currentId=id;
natWin=win;
width=_width;
height=_height;
thrInfo=_thrInfo;
}
bool NativeRenderThread::start() {
bool RenderThread::start() {
if (isRunning_) {
return true;
}
isRunning_ = true;
rdThread = std::thread(&NativeRenderThread::renderLoop, this);
rdThread = std::thread(&RenderThread::renderLoop, this);
return true;
}
void NativeRenderThread::stop() {
void RenderThread::stop() {
if (!isRunning_) {
return;
}
@ -52,9 +47,9 @@ void NativeRenderThread::stop() {
if (rdThread.joinable()) {
rdThread.join();
}
EGLCoreMgr->destroy();
eglSubCore->destroy(thrInfo.eglCore->GetEGLDisplay());
}
void NativeRenderThread::initFontMgr(){
void RenderThread::initFontMgr(){
ftMgr=Font_FontMgr::GetInstance();
ftMgr->InitFontDataBase();
ftMgr->SetPrintErrors(true);
@ -89,24 +84,20 @@ void NativeRenderThread::initFontMgr(){
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "OCCT","OCCT Font Path: %{public}s", fta->FontPath(Font_FontAspect_Regular).ToCString());
}
}
void NativeRenderThread::renderLoop() {
void RenderThread::renderLoop() {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "renderLoop",
"Thread ID: %{public}s",
reinterpret_cast<std::ostringstream&>(std::ostringstream() << std::this_thread::get_id()).str().c_str());
//初始化OCCT字体管理
initFontMgr();
if(EGLCoreMgr==nullptr){
EGLCoreMgr=new EGLCore();
}
if(EGLCoreMgr->InitEglCtx(natWin, currentId)){
NativeRender* render=new NativeRender(width,height);
RenderCoreMgr[currentId]=render;
if (render->init(EGLCoreMgr->GetDisplay(),EGLCoreMgr->GetContext(),EGLCoreMgr->GetConfig())) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRenderInit ","Render Init Done");
}else{
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRenderInit","Render Init Failed");
EGLCoreMgr->destroy();
}
eglSubCore=new EGLSubCore();
eglSubCore->InitEGLSubCore(thrInfo.eglCore->GetEGLDisplay(), thrInfo.eglCore->GetEGLConfig(), thrInfo.win);
Render* render=new Render(thrInfo.width,thrInfo.height);
if (render->init(thrInfo.eglCore->GetEGLDisplay(),eglSubCore->eglCtx,thrInfo.eglCore->GetEGLConfig())) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRenderInit ","Render Init Done");
}else{
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRenderInit","Render Init Failed");
eglSubCore->destroy(thrInfo.eglCore->GetEGLDisplay());
}
while (isRunning_) {
RenderCommand command;
@ -127,27 +118,27 @@ void NativeRenderThread::renderLoop() {
if (hasCommand) {
switch (command.type) {
case CMD_LOAD_MODEL:
RenderCoreMgr[currentId]->loadModel(command.param1);
render->loadModel(command.param1);
break;
case CMD_SET_ROTATION:
RenderCoreMgr[currentId]->setRotation(command.param2, command.param3);
render->setRotation(command.param2, command.param3);
break;
case CMD_SET_TRANSLATION:
RenderCoreMgr[currentId]->setTranslation(command.param2, command.param3);
render->setTranslation(command.param2, command.param3);
break;
case CMD_RESET_VIEW:
RenderCoreMgr[currentId]->resetView();
render->resetView();
break;
case CMD_SET_CLEAR_COLOR:
RenderCoreMgr[currentId]->setClearColor(command.param2, command.param3, command.param4, command.param5);
render->setClearColor(command.param2, command.param3, command.param4, command.param5);
break;
case CMD_RESIZE:
rdWidth = static_cast<int>(command.param2);
rdHeight = static_cast<int>(command.param3);
RenderCoreMgr[currentId]->resize(rdWidth, rdHeight);
render->resize(rdWidth, rdHeight);
break;
case CMD_SWITCH_VIEW:
RenderCoreMgr[currentId]->SwitchView(command.param1);
render->SwitchView(command.param1);
break;
case CMD_EXIT:
isRunning_ = false;
@ -158,9 +149,9 @@ void NativeRenderThread::renderLoop() {
break;
}
// 渲染
EGLCoreMgr->makeCurrent();
RenderCoreMgr[currentId]->render();
EGLCoreMgr->swapBuffers();
eglSubCore->makeCurrent(thrInfo.eglCore->GetEGLDisplay());
render->render();
eglSubCore->swapBuffers(thrInfo.eglCore->GetEGLDisplay());
// 调用渲染完成回调
Callback callback;
{
@ -177,7 +168,7 @@ void NativeRenderThread::renderLoop() {
}
}
void NativeRenderThread::loadModel(const std::string& filePath) {
void RenderThread::loadModel(const std::string& filePath) {
std::lock_guard<std::mutex> lock(commandMutex_);
RenderCommand cmd(CMD_LOAD_MODEL);
cmd.param1 = filePath;
@ -185,7 +176,7 @@ void NativeRenderThread::loadModel(const std::string& filePath) {
commandCondition_.notify_one();
}
void NativeRenderThread::setRotation(float xAngle, float yAngle) {
void RenderThread::setRotation(float xAngle, float yAngle) {
std::lock_guard<std::mutex> lock(commandMutex_);
RenderCommand cmd(CMD_SET_ROTATION);
cmd.param2 = xAngle;
@ -194,7 +185,7 @@ void NativeRenderThread::setRotation(float xAngle, float yAngle) {
commandCondition_.notify_one();
}
void NativeRenderThread::setTranslation(float x, float y) {
void RenderThread::setTranslation(float x, float y) {
std::lock_guard<std::mutex> lock(commandMutex_);
RenderCommand cmd(CMD_SET_TRANSLATION);
cmd.param2 = x;
@ -203,19 +194,19 @@ void NativeRenderThread::setTranslation(float x, float y) {
commandCondition_.notify_one();
}
void NativeRenderThread::resetView() {
void RenderThread::resetView() {
std::lock_guard<std::mutex> lock(commandMutex_);
commandQueue_.push(RenderCommand(CMD_RESET_VIEW));
commandCondition_.notify_one();
}
void NativeRenderThread::swicthView(std::string strView) {
void RenderThread::swicthView(std::string strView) {
std::lock_guard<std::mutex> lock(commandMutex_);
RenderCommand cmd(CMD_SWITCH_VIEW);
cmd.param1 = strView;
commandQueue_.push(RenderCommand(cmd));
commandCondition_.notify_one();
}
void NativeRenderThread::setClearColor(float r, float g, float b, float a) {
void RenderThread::setClearColor(float r, float g, float b, float a) {
std::lock_guard<std::mutex> lock(commandMutex_);
RenderCommand cmd(CMD_SET_CLEAR_COLOR);
cmd.param2 = r;
@ -226,7 +217,7 @@ void NativeRenderThread::setClearColor(float r, float g, float b, float a) {
commandCondition_.notify_one();
}
void NativeRenderThread::resizeWindow(int width, int height) {
void RenderThread::resizeWindow(int width, int height) {
std::lock_guard<std::mutex> lock(commandMutex_);
RenderCommand cmd(CMD_RESIZE);
cmd.param2 = static_cast<float>(width);
@ -235,7 +226,7 @@ void NativeRenderThread::resizeWindow(int width, int height) {
commandCondition_.notify_one();
}
void NativeRenderThread::registerRenderCompleteCallback(Callback callback) {
void RenderThread::registerRenderCompleteCallback(Callback callback) {
std::lock_guard<std::mutex> lock(callbackMutex_);
renderCompleteCallback_ = callback;
}

View File

@ -1,5 +1,7 @@
#ifndef NATIVE_RENDER_THREAD_H
#define NATIVE_RENDER_THREAD_H
#include <native_window/external_window.h>
#include <thread>
#include <atomic>
#include <mutex>
@ -7,8 +9,9 @@
#include <queue>
#include <functional>
#include "EGLCore.h"
#include "NativeRender.h"
#include "../EGLMgr/EGLCore.h"
#include "../EGLMgr/EGLSubCore.h"
#include "Render.h"
#include <Font_FontMgr.hxx>
#include <AIS_TextLabel.hxx>
@ -16,15 +19,21 @@
namespace NativeOpenCAX {
struct ThreadInfo{
int width;
int height;
OHNativeWindow* win;
EGLCore* eglCore;
};
class NativeRenderThread {
class RenderThread {
public:
NativeRenderThread();
~NativeRenderThread();
RenderThread();
~RenderThread();
bool start();
void stop();
void InitRender(std::string id,int width,int height,OHNativeWindow* window);
void InitRender(ThreadInfo thrInfo);
void loadModel(const std::string& filePath);
void setCameraRotationMode(bool state);
void setRotation(float xAngle, float yAngle);
@ -41,14 +50,13 @@ private:
void renderLoop();
std::thread rdThread;
std::atomic<bool> isRunning_;
std::string currentId;
std::map<std::string,NativeRender*> RenderCoreMgr;
EGLCore* EGLCoreMgr;
std::mutex commandMutex_;
std::condition_variable commandCondition_;
OHNativeWindow* natWin;
int width;
int height;
ThreadInfo thrInfo;
Render* render;
EGLSubCore* eglSubCore;
enum CommandType {
CMD_LOAD_MODEL,
CMD_SET_ROTATION,

View File

@ -8,7 +8,6 @@
#define OPENCAX_OPENGLGRAPHICDRIVER_H
#include <EGL/egl.h>
#include "NativeEGLOCCT/EGLCore.h"
#include "NativeEGLOCCT/common.h"
#include <OpenGl_GraphicDriver.hxx>
#include <Graphic3d_GraphicDriver.hxx>