修复部分多例代码

This commit is contained in:
JackLee 2026-04-02 19:40:03 +08:00
parent 68a4979a93
commit c0d534af0a
14 changed files with 372 additions and 215 deletions

View File

@ -4,46 +4,11 @@
#ifndef NATIVE_TAG
#define NATIVE_TAG "EGLCore"
#endif
namespace NativeOpenCAX {
EGLCore::EGLCore()
: eglDisplay(EGL_NO_DISPLAY),
eglContext(EGL_NO_CONTEXT),
eglSurface(EGL_NO_SURFACE),
nativeWindow(nullptr)
{
}
EGLCore::~EGLCore() {
destroy();
}
bool EGLCore::init(OHNativeWindow* window) {
if (!window) {
printf("Native window is null\n");
return false;
}
nativeWindow=window;
HILOG_INFO(NATIVE_TAG,"Current Thread ID: %{public}d",std::this_thread::get_id());
// 获取EGL display
eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (eglDisplay == EGL_NO_DISPLAY) {
HILOG_ERROR(NATIVE_TAG,"eglGetDisplay failed:%{public}d",glGetError());
return false;
}
// 初始化EGL
EGLint majorVersion;
EGLint minorVersion;
if (!eglInitialize(eglDisplay, &majorVersion, &minorVersion)) {
HILOG_ERROR(NATIVE_TAG,"eglInitialize failed:%{public}d",glGetError());
return false;
}
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCoreInit","EGLDisplay version:%{public}d",majorVersion+"."+minorVersion);
HILOG_ERROR(NATIVE_TAG,"EGLDisplay version:%{public}d%{public}d",majorVersion,minorVersion);
// 配置EGL
EGLint attribs[] = {
EGLint cfgAttribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_BLUE_SIZE, 8,
@ -55,69 +20,227 @@ bool EGLCore::init(OHNativeWindow* window) {
EGL_NONE
};
const EGLint maxConfigSize = 1;
EGLint numConfigs;
if (!eglChooseConfig(eglDisplay, attribs, &eglConfig, maxConfigSize, &numConfigs)) {
HILOG_ERROR(NATIVE_TAG,"eglChooseConfig: unable to choose configs");
return false;
}
// 创建EGL surface
eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (NativeWindowType)nativeWindow, nullptr);
if (eglSurface == EGL_NO_SURFACE) {
HILOG_ERROR(NATIVE_TAG,"EGL_NO_SURFACE");
return false;
}
// 创建EGL context
EGLint contextAttribs[] = {
EGLint ctxAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs);
if (eglContext == EGL_NO_CONTEXT) {
HILOG_ERROR(NATIVE_TAG,"EGL_NO_CONTEXT");
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;
}
// 激活上下文
makeCurrent();
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;
}
// 检查GL错误
GLenum glError = glGetError();
if (glError != GL_NO_ERROR) {
HILOG_ERROR(NATIVE_TAG,"glError:",glError);
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() {
if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) {
HILOG_ERROR(NATIVE_TAG,"eglMakeCurrent failed: 0x%{public}x\n:",eglGetError());
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() {
return eglSwapBuffers(eglDisplay, eglSurface);
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) {
if (eglContext != EGL_NO_CONTEXT) {
eglDestroyContext(eglDisplay, eglContext);
eglContext = EGL_NO_CONTEXT;
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);
}
if (eglSurface != EGL_NO_SURFACE) {
eglDestroySurface(eglDisplay, eglSurface);
eglSurface = EGL_NO_SURFACE;
// 销毁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

@ -12,33 +12,45 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef EGLCORE_H
#define EGLCORE_H
#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 init(OHNativeWindow* window);
bool InitEglCtx(OHNativeWindow* window,std::string id);
std::string GetCurrentXCompId();
void makeCurrent();
bool swapBuffers();
void destroy();
EGLSurface getSurface() const { return eglSurface; }
EGLContext getContext() const { return eglContext; }
EGLDisplay getDisplay() const { return eglDisplay; }
EGLConfig getConfig() const { return eglConfig; }
OHNativeWindow* getOHNativeWindow()const{return nativeWindow;}
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;
EGLContext eglContext;
EGLSurface eglSurface;
EGLConfig eglConfig;
OHNativeWindow* nativeWindow;
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

@ -10,6 +10,7 @@
#include "common.h"
#include <random>
#include <map>
#include <iostream>
#define COLUMN_MARGIN 10
#define XC_WIDTH 800
#define XC_HEIGHT 600
@ -30,11 +31,12 @@ NativeMgr NativeMgr::pluginManager_;
OH_NativeXComponent_Callback NativeMgr::xSurfaceTouchEventCallBack;
OH_NativeXComponent_MouseEvent_Callback NativeMgr::xMouseEventCallBack;
std::string comId;
std::string nodeId;
std::string NativeMgr::crtXCompId;
std::unordered_map<std::string,NXInfo*> NativeMgr::NxInfos;
int32_t NativeMgr::hasDraw_ = 0;
int32_t NativeMgr::hasChangeColor_ = 0;
static std::map<int64_t, std::shared_ptr<NativeRenderThread>> renderThreadMap;
static std::map<std::string, std::shared_ptr<NativeRenderThread>> rdThreads;
static std::mutex mapMutex;
std::string uuid_v4() {
@ -57,15 +59,13 @@ std::string uuid_v4() {
return ss.str();
}
NativeMgr::~NativeMgr() {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "~NativeMgr");
nativeXComponentMap_.clear();
int64_t id = 0;
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) != renderThreadMap.end()) {
renderThreadMap[id]->stop();
renderThreadMap.erase(id);
if (rdThreads.find(crtXCompId) != rdThreads.end()) {
rdThreads[crtXCompId]->stop();
rdThreads.erase(crtXCompId);
}
for (auto iter = pluginManagerMap_.begin(); iter != pluginManagerMap_.end(); ++iter) {
@ -142,46 +142,40 @@ void NativeMgr::OnSurfaceCreated(OH_NativeXComponent *component, void *window) {
}
OH_NativeXComponent_GetXComponentSize(component, window, &bfWidth, &bfHeight);
int64_t id = 0;
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) == renderThreadMap.end()) {
if (rdThreads.find(crtXCompId) == rdThreads.end()) {
auto renderThread = std::make_shared<NativeRenderThread>();
renderThread->initNativeReader(bfWidth, bfHeight);
HILOG_ERROR(NATIVE_TAG,"uint64_t bfSize:%{public}dX%{public}d",bfWidth,bfHeight);
renderThreadMap[id] = renderThread;
renderThread->start(reinterpret_cast<OHNativeWindow*>(window));
rdThreads[crtXCompId] = renderThread;
renderThread->InitRender(crtXCompId,bfWidth, bfHeight,reinterpret_cast<OHNativeWindow*>(window));
renderThread->start();
}
}
void NativeMgr::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceDestroyed");
int64_t id = 0;
{
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) != renderThreadMap.end()) {
renderThreadMap[id]->stop();
renderThreadMap.erase(id);
if (rdThreads.find(crtXCompId) != rdThreads.end()) {
rdThreads[crtXCompId]->stop();
rdThreads.erase(crtXCompId);
}
}
}
void NativeMgr::OnSurfaceChanged(OH_NativeXComponent *component, void *window) {
OH_NativeXComponent_GetXComponentSize(component, window, &afWidth, &afHeight);
int64_t id = 0;
{
if(bfWidth==afWidth && bfHeight==afHeight){
return;
}
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) != renderThreadMap.end()) {
if (rdThreads.find(crtXCompId) != rdThreads.end()) {
HILOG_ERROR(NATIVE_TAG,"uint64_t Size:%{public}dX%{public}d",bfWidth,bfHeight);
bfWidth=afWidth;
bfHeight=afHeight;
renderThreadMap[id]->resizeWindow(bfWidth, bfHeight);
rdThreads[crtXCompId]->resizeWindow(bfWidth, bfHeight);
}
}
}
void OnMouseEventCB(OH_NativeXComponent* component, void* window) {
auto* pluginManager = NativeMgr::GetInstance();
if (!pluginManager || !window) {
@ -212,9 +206,8 @@ void NativeMgr::OnMouseEvent(OH_NativeXComponent *comp, void *win) {
return;
}
NativeMgr::timestamp=mouseEvent.timestamp;
int64_t id = 0;
auto it = renderThreadMap.find(id);
if (it == renderThreadMap.end()) {
auto it = rdThreads.find(crtXCompId);
if (it == rdThreads.end()) {
HILOG_WARN(NATIVE_TAG, "Render thread not found for rotation.");
return;
}
@ -302,8 +295,10 @@ NativeMgr::NativeMgr() {
xMouseEventCallBack.DispatchMouseEvent= OnMouseEventCB;
}
// 创建节点组件
ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) {
nodeId=tag;
ArkUI_NodeHandle CreateNodeHandle(void* userData) {
auto ud=static_cast<NXInfo*>(userData);
HILOG_INFO(NATIVE_TAG,"CreateNodeHandle NODE ID:%{public}s",ud->nid.c_str());
HILOG_INFO(NATIVE_TAG,"CreateNodeHandle XCOMP ID:%{public}s",ud->xid.c_str());
// 创建Node也名创建ROW Column等容器
ArkUI_NodeHandle nodeHandel = nodeAPI->createNode(ARKUI_NODE_RELATIVE_CONTAINER);
// 节点默认宽度or高度
@ -312,17 +307,16 @@ ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) {
// 参数1:指向数值数组
// 参数2:数组元素个数
// 参数3:属性名(可隐藏)
ArkUI_AttributeItem nodeMarginItem = {nodeMarginData, 2};
ArkUI_AttributeItem nodeMarginItem = {nodeMarginData};
// 设置Node宽度or高度
nodeAPI->setAttribute(nodeHandel, NODE_MARGIN, &nodeMarginItem);
NativeMgr::nodeHandleMap_[tag]=nodeHandel;
NativeMgr::nodeHandleMap_[ud->nid]=nodeHandel;
// 创建XComponent组件
// 组件类型Item
ArkUI_NumberValue comTypeData[] = {ARKUI_XCOMPONENT_TYPE_SURFACE};
ArkUI_AttributeItem comTypeItem = {comTypeData, 1};
ArkUI_AttributeItem comTypeItem = {comTypeData};
// 组件ID Item
comId=uuid_v4();
ArkUI_AttributeItem comIdItem = {.string = comId.c_str(), .size = 1};
ArkUI_AttributeItem comIdItem = {.string = ud->xid.c_str()};
// 组件Surface Size
// 创建组件
ArkUI_NodeHandle xc;
@ -334,10 +328,10 @@ ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) {
// 焦点设置
ArkUI_NumberValue focusable[] = {1};
focusable[0].i32 = 1;
ArkUI_AttributeItem focusableItem = {focusable, 1};
ArkUI_AttributeItem focusableItem = {focusable};
nodeAPI->setAttribute(xc, NODE_FOCUSABLE, &focusableItem);
// 节点ID
ArkUI_AttributeItem nodeIdItem = {.string = uuid_v4().c_str(), .size = 1};
ArkUI_AttributeItem nodeIdItem = {.string = ud->nid.c_str()};
nodeAPI->setAttribute(xc, NODE_ID, &nodeIdItem);
auto *nativeXComponent = OH_NativeXComponent_GetNativeXComponent(xc);
@ -404,23 +398,32 @@ napi_value NativeMgr::initNativeNode(napi_env env, napi_callback_info info) {
return nullptr;
}
//获取传入NodeContent实例
size_t argCnt = 3;
napi_value args[3] = {nullptr,nullptr,nullptr};
size_t argCnt = 4;
napi_value args[4] = {nullptr};
if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
HILOG_ERROR(NATIVE_TAG,"CreateNativeNode napi_get_cb_info failed");
}
bool type;
NXInfo* nxInfo=new NXInfo;
nxInfo->nid=value2String(env, args[0]);
nxInfo->xid=value2String(env, args[1]);
napi_get_value_bool(env, args[2], &type);
crtXCompId=nxInfo->xid;
NxInfos[nxInfo->xid]=nxInfo;
ArkUI_NodeContentHandle _nodeContentHandle = nullptr;
// 获取ArkTS侧创建的NodeContent对象映射到Native侧的
OH_ArkUI_GetNodeContentFromNapiValue(env, args[2], &_nodeContentHandle);
OH_ArkUI_GetNodeContentFromNapiValue(env, args[3], &_nodeContentHandle);
// 查询指定的模块接口名
nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1"));
//下面的代码主要用于创建一个Native侧和arkui侧绑定数据的结构传递传输的操作
//node_data可以理解为一个结构体等等之类的指针
// 生成节点名采用NODE_ID_+UUID
std::string node_data = uuid_v4();
HILOG_INFO(NATIVE_TAG,"NODE_DATA:%{public}d",node_data.c_str());
HILOG_INFO(NATIVE_TAG,"Native NODE ID:%{public}s",nxInfo->nid.c_str());
HILOG_INFO(NATIVE_TAG,"Native XCOMP ID:%{public}s",nxInfo->xid.c_str());
// 在NodeContent对象上保存自定义数据。
int32_t ret = OH_ArkUI_NodeContent_SetUserData(_nodeContentHandle, new std::string(node_data));
int32_t ret = OH_ArkUI_NodeContent_SetUserData(_nodeContentHandle, static_cast<void*>(nxInfo));
if (ret != ARKUI_ERROR_CODE_NO_ERROR) {
HILOG_ERROR(NATIVE_TAG,"setUserData failed error=%{public}d",ret);
}
@ -429,15 +432,15 @@ napi_value NativeMgr::initNativeNode(napi_env env, napi_callback_info info) {
// 获取Node连接事件的对应Node的Handle
ArkUI_NodeContentHandle handle = OH_ArkUI_NodeContentEvent_GetNodeContentHandle(event);
// 获取对应Handle的UserData
std::string *userDate = reinterpret_cast<std::string *>(OH_ArkUI_NodeContent_GetUserData(handle));
void* ud=OH_ArkUI_NodeContent_GetUserData(handle);
if (OH_ArkUI_NodeContentEvent_GetEventType(event) == NODE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW) {
ArkUI_NodeHandle testNode;
if (userDate) {
testNode = CreateNodeHandle(*userDate);
delete userDate;
userDate = nullptr;
if (ud) {
testNode = CreateNodeHandle(ud);
delete ud;
ud = nullptr;
} else {
testNode = CreateNodeHandle("noUserData");
//testNode = CreateNodeHandle(nullptr);
}
// 向NodeContent中添加子组件
OH_ArkUI_NodeContent_AddNode(handle, testNode);
@ -490,11 +493,10 @@ napi_value NativeMgr::NapiLoadModel(napi_env env, napi_callback_info info) {
napi_value args[1];
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
std::string path = value2String(env, args[0]);
int64_t id = 0;
{
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) != renderThreadMap.end()) {
renderThreadMap[id]->loadModel(std::string(path));
if (rdThreads.find(crtXCompId) != rdThreads.end()) {
rdThreads[crtXCompId]->loadModel(std::string(path));
}
}
return nullptr;
@ -506,11 +508,10 @@ napi_value NativeMgr::SwitchView(napi_env env, napi_callback_info info){
napi_value args[1];
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
std::string viewName = value2String(env, args[0]);
int64_t id = 0;
{
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) != renderThreadMap.end()) {
renderThreadMap[id]->swicthView(viewName);
if (rdThreads.find(crtXCompId) != rdThreads.end()) {
rdThreads[crtXCompId]->swicthView(viewName);
}
}
return nullptr;

View File

@ -35,11 +35,16 @@
namespace NativeOpenCAX {
constexpr const int ZERO_ARG = 0;
constexpr const int FIRST_ARG = 1;
constexpr const int SECOND_ARG = 2;
constexpr const int THIRD_ARG = 3;
constexpr const int FRAME_COUNT = 50;
struct NXInfo{
std::string nid;
std::string xid;
};
class NativeMgr {
public:
@ -81,7 +86,8 @@ private:
public:
// [StartExclude plugin_manager_h_part]
OH_NativeXComponent_TouchEvent touchEvent_;
static std::string crtXCompId;
static std::unordered_map<std::string,NXInfo*> NxInfos;
std::string modelPath_;
//窗体Size改变前
uint64_t bfWidth;

View File

@ -29,10 +29,9 @@ v3dwin(new V3dWin)
NativeRender::~NativeRender() { shapes_.clear(); }
bool NativeRender::init(EGLCore &_eglCore) {
eglCore = _eglCore;
bool NativeRender::init(EGLDisplay eglDisp,EGLContext ctx,EGLConfig eglConfig) {
//初始化OpenGL
if (!v3dogd->InitV3dOGD(eglCore)) {
if (!v3dogd->InitV3dOGD(eglDisp,ctx,eglConfig)) {
HILOG_ERROR(NATIVE_TAG, "Init GraphicDriver Fail!");
return false;
}
@ -55,7 +54,7 @@ bool NativeRender::init(EGLCore &_eglCore) {
return false;
}
//初始化视图
if (!v3dview->InitV3dView(v3dviewer->viewer,v3dwin->win)) {
if (!v3dview->InitV3dView(v3dviewer->viewer,ctx,v3dwin->win)) {
HILOG_ERROR(NATIVE_TAG, "Init View Fail!");
return false;
} else {

View File

@ -32,7 +32,7 @@ public:
NativeRender(int width, int height);
~NativeRender();
bool init(EGLCore& eglCore);
bool init(EGLDisplay eglDisp,EGLContext ctx,EGLConfig eglConfig);
bool loadModel(const std::string& filePath);
void render();
void resize(int width, int height);
@ -48,7 +48,6 @@ public:
private:
int width;
int height;
EGLCore eglCore;
V3dTri* v3dTri;
V3dTriCube* v3dTriCube;
V3dCa* v3dcr;

View File

@ -8,27 +8,31 @@ namespace NativeOpenCAX {
NativeRenderThread::NativeRenderThread()
: isRunning_(false),
nativeWindow_(nullptr)
EGLCoreMgr(nullptr),
RenderCoreMgr(std::map<std::string,NativeRender*>())
{
eglCore_ = new EGLCore();
}
NativeRenderThread::~NativeRenderThread() {
stop();
}
void NativeRenderThread::initNativeReader(int width,int height){
renderer_= new NativeRender(width,height);
void NativeRenderThread::InitRender(std::string id,int _width,int _height,OHNativeWindow* win){
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;
}
bool NativeRenderThread::start(OHNativeWindow* window) {
bool NativeRenderThread::start() {
if (isRunning_) {
return true;
}
nativeWindow_ = window;
isRunning_ = true;
renderThread_ = std::thread(&NativeRenderThread::renderLoop, this);
rdThread = std::thread(&NativeRenderThread::renderLoop, this);
return true;
}
@ -45,17 +49,12 @@ void NativeRenderThread::stop() {
}
commandCondition_.notify_one();
if (renderThread_.joinable()) {
renderThread_.join();
if (rdThread.joinable()) {
rdThread.join();
}
eglCore_->destroy();
}
void NativeRenderThread::renderLoop() {
// 初始化EGL
if (!eglCore_->init(nativeWindow_)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCoreInit","Failed to initialize EGL");
EGLCoreMgr->destroy();
}
void NativeRenderThread::initFontMgr(){
ftMgr=Font_FontMgr::GetInstance();
ftMgr->InitFontDataBase();
ftMgr->SetPrintErrors(true);
@ -89,12 +88,25 @@ void NativeRenderThread::renderLoop() {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "OCCT","OCCT Font: %{public}s", fta->FontName().ToCString());
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "OCCT","OCCT Font Path: %{public}s", fta->FontPath(Font_FontAspect_Regular).ToCString());
}
// 初始化OCCT渲染器
if (!renderer_->init(*eglCore_)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRenderInit","Failed to initialize OCCT renderer");
eglCore_->destroy();
}
void NativeRenderThread::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();
}
}
while (isRunning_) {
RenderCommand command;
@ -115,27 +127,27 @@ void NativeRenderThread::renderLoop() {
if (hasCommand) {
switch (command.type) {
case CMD_LOAD_MODEL:
renderer_->loadModel(command.param1);
RenderCoreMgr[currentId]->loadModel(command.param1);
break;
case CMD_SET_ROTATION:
renderer_->setRotation(command.param2, command.param3);
RenderCoreMgr[currentId]->setRotation(command.param2, command.param3);
break;
case CMD_SET_TRANSLATION:
renderer_->setTranslation(command.param2, command.param3);
RenderCoreMgr[currentId]->setTranslation(command.param2, command.param3);
break;
case CMD_RESET_VIEW:
renderer_->resetView();
RenderCoreMgr[currentId]->resetView();
break;
case CMD_SET_CLEAR_COLOR:
renderer_->setClearColor(command.param2, command.param3, command.param4, command.param5);
RenderCoreMgr[currentId]->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);
renderer_->resize(rdWidth, rdHeight);
RenderCoreMgr[currentId]->resize(rdWidth, rdHeight);
break;
case CMD_SWITCH_VIEW:
renderer_->SwitchView(command.param1);
RenderCoreMgr[currentId]->SwitchView(command.param1);
break;
case CMD_EXIT:
isRunning_ = false;
@ -146,9 +158,9 @@ void NativeRenderThread::renderLoop() {
break;
}
// 渲染
eglCore_->makeCurrent();
renderer_->render();
eglCore_->swapBuffers();
EGLCoreMgr->makeCurrent();
RenderCoreMgr[currentId]->render();
EGLCoreMgr->swapBuffers();
// 调用渲染完成回调
Callback callback;
{

View File

@ -16,14 +16,15 @@
namespace NativeOpenCAX {
class NativeRenderThread {
public:
NativeRenderThread();
~NativeRenderThread();
bool start(OHNativeWindow* window);
bool start();
void stop();
void initNativeReader(int width,int height);
void InitRender(std::string id,int width,int height,OHNativeWindow* window);
void loadModel(const std::string& filePath);
void setCameraRotationMode(bool state);
void setRotation(float xAngle, float yAngle);
@ -36,18 +37,18 @@ public:
void registerRenderCompleteCallback(Callback callback);
private:
void initFontMgr();
void renderLoop();
std::thread renderThread_;
std::thread rdThread;
std::atomic<bool> isRunning_;
OHNativeWindow* nativeWindow_;
EGLCore* eglCore_;
NativeRender* renderer_;
std::string currentId;
std::map<std::string,NativeRender*> RenderCoreMgr;
EGLCore* EGLCoreMgr;
std::mutex commandMutex_;
std::condition_variable commandCondition_;
OHNativeWindow* natWin;
int width;
int height;
enum CommandType {
CMD_LOAD_MODEL,
CMD_SET_ROTATION,
@ -75,6 +76,7 @@ private:
Handle(Font_FontMgr) ftMgr ;
int rdWidth=0;
int rdHeight=0;
};
} // namespace NaitveRenderThread
#endif //NATIVE_RENDER_THREAD_H

View File

@ -14,13 +14,13 @@ namespace NativeOpenCAX {
V3dOGD::V3dOGD() : graphicDriver(nullptr), displayConnection(nullptr) {}
V3dOGD::~V3dOGD() {}
bool V3dOGD::InitV3dOGD(EGLCore& eglCore) {
bool V3dOGD::InitV3dOGD(EGLDisplay eglDisp,EGLContext ctx,EGLConfig eglConfig) {
try {
displayConnection = new Aspect_DisplayConnection();
graphicDriver = new OpenGl_GraphicDriver(displayConnection, false);
graphicDriver->ChangeOptions().buffersNoSwap = true;
graphicDriver->InitEglContext(eglGetCurrentDisplay(), eglGetCurrentContext(), eglCore.getConfig());
graphicDriver->InitEglContext(eglDisp, ctx, eglConfig);
HILOG_INFO(NATIVE_TAG, "InitGraphicDriver Done");
return true;
} catch (std::exception &e) {

View File

@ -18,7 +18,7 @@ class V3dOGD{
public:
V3dOGD();
~V3dOGD();
bool InitV3dOGD(EGLCore& eglCore);
bool InitV3dOGD(EGLDisplay eglDisp,EGLContext ctx,EGLConfig eglConfig);
public:
Handle(OpenGl_GraphicDriver) graphicDriver;
Handle(Aspect_DisplayConnection) displayConnection;

View File

@ -18,10 +18,10 @@ namespace NativeOpenCAX {
V3dView::V3dView() : view(nullptr) {}
V3dView::~V3dView() {}
bool V3dView::InitV3dView(Handle(V3d_Viewer) & viewer,Handle(Aspect_NeutralWindow)& win) {
bool V3dView::InitV3dView(Handle(V3d_Viewer) & viewer,EGLContext ctx,Handle(Aspect_NeutralWindow)& win) {
try {
view = viewer->CreateView();
view->SetWindow(win, (Aspect_RenderingContext)eglGetCurrentContext());
view->SetWindow(win, ctx);
HILOG_INFO(NATIVE_TAG, "InitView Done");
return true;
} catch (std::exception &e) {

View File

@ -20,7 +20,7 @@ class V3dView{
public:
V3dView();
~V3dView();
bool InitV3dView(Handle(V3d_Viewer)& viewer,Handle(Aspect_NeutralWindow)& win);
bool InitV3dView(Handle(V3d_Viewer)& viewer,EGLContext ctx,Handle(Aspect_NeutralWindow)& win);
void InitViewOption();
void SetClearColor(float r, float g, float b, float a);
void MustBeResized();

View File

@ -2,6 +2,6 @@ export interface NativeXOpenCAX {
setFrameRate(nodeId: string, min: number, max: number, expected: number): void;
setNeedSoftKeyboard(nodeId: string, need: boolean): void;
}
export function InitNativeNode(xId:string,initType:boolean,nodeContent: any): void;
export function InitNativeNode(nId:string,xId:string,initType:boolean,nodeContent: any): void;
export function loadModel(stepFilePath: string): void;
export function switchView(viewName: string): void;

View File

@ -5,6 +5,7 @@ import { mwInfo } from '../AppStorageV2Class';
import {NodeContent} from '@kit.ArkUI';
export interface XComp{
nId?:string;
xId?:string;
name?:string;
icon?:string;
@ -32,16 +33,18 @@ function XNRandomId(): string {
export function InitXCompNode(name:string){
//数组为0表示初始化,Native侧这初始化主上下文,否则Native侧初始化共享上下文
let ncInfo:XComp={};
ncInfo.xId=XNRandomId();
ncInfo.name=name+XNRandomId();
ncInfo.nId='n_'+XNRandomId();
ncInfo.xId='x_'+XNRandomId();
ncInfo.name=name+ncInfo.xId;
ncInfo.node=new NodeContent();
if(XComps.length==0)
{
NativeOpenCAX.InitNativeNode(ncInfo.xId,true,ncInfo.node);
NativeOpenCAX.InitNativeNode(ncInfo.nId,ncInfo.xId,true,ncInfo.node);
}else{
NativeOpenCAX.InitNativeNode(ncInfo.xId,false,ncInfo.node);
NativeOpenCAX.InitNativeNode(ncInfo.nId,ncInfo.xId,false,ncInfo.node);
}
XComps.push(ncInfo);
console.log(`ArkUI Node ID: ${ncInfo.nId}`);
console.log(`ArkUI XComp ID: ${ncInfo.xId}`);
}