完善渲染整体逻辑.

已知BUG.OCCT的view没有绑定鸿蒙OHWindows*的窗口对象
This commit is contained in:
JackLee 2026-02-26 17:47:53 +08:00
parent 77dd6edf5f
commit eed0b54b30
13 changed files with 806 additions and 970 deletions

View File

@ -28,14 +28,16 @@ endforeach()
# #
add_library(opencax SHARED add_library(opencax SHARED
# Header # Header
NativeEGLOCCT/EGLConst.h
NativeEGLOCCT/EGLCore.h NativeEGLOCCT/EGLCore.h
NativeEGLOCCT/NativeRender.h
NativeEGLOCCT/NativeRenderThread.h
NativeEGLOCCT/NativeManager.h NativeEGLOCCT/NativeManager.h
# Cpp Src # Cpp Src
NativeEGLOCCT/EGLCore.cpp NativeEGLOCCT/EGLCore.cpp
NativeEGLOCCT/NativeRender.cpp
NativeEGLOCCT/NativeRenderThread.cpp
NativeEGLOCCT/NativeManager.cpp NativeEGLOCCT/NativeManager.cpp
napi_init.cpp napi_init.cpp)
)
# #
find_library(EGL-lib EGL) find_library(EGL-lib EGL)

View File

@ -1,159 +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 NATIVEXCOMPONENT_EGLCONST_H
#define NATIVEXCOMPONENT_EGLCONST_H
// [Start egl_const_h]
// EGLConst.h
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
const unsigned int LOG_PRINT_DOMAIN = 0xFF00;
/**
* Program
*/
const GLuint PROGRAM_ERROR = 0;
/**
*
*/
const GLint POSITION_ERROR = -1;
/**
* x坐标
*/
const int DEFAULT_X_POSITION = 0;
/**
* y坐标
*/
const int DEFAULT_Y_POSITION = 0;
/**
* Gl
*/
const GLfloat GL_RED_DEFAULT = 0.0;
/**
* Gl 绿
*/
const GLfloat GL_GREEN_DEFAULT = 0.0;
/**
* Gl
*/
const GLfloat GL_BLUE_DEFAULT = 0.0;
/**
* Gl
*/
const GLfloat GL_ALPHA_DEFAULT = 1.0;
/**
* Pointer
*/
const GLint POINTER_SIZE = 2;
/**
* Triangle fan
*/
const GLsizei TRIANGLE_FAN_SIZE = 4;
/**
* 50%
*/
const float FIFTY_PERCENT = 0.5;
/**
*
*/
const char POSITION_NAME[] = "a_position";
// [StartExclude egl_const_h]
/**
* numeric value 0.
*/
const int NUM_0 = 0;
/**
* numeric value 4.
*/
const int NUM_4 = 4;
// [EndExclude egl_const_h]
/**
* #f4f4f4.
*/
const GLfloat BACKGROUND_COLOR[] = {244.0f / 255, 244.0f / 255, 244.0f / 255, 1.0f};
// [StartExclude egl_const_h]
/**
* Background color #ffffff00.
*/
const GLfloat TRANSPARENT_COLOR[] = {255.0f / 255, 255.0f / 255, 255.0f / 255, 0.0f};
// [EndExclude egl_const_h]
/**
* Draw #7E8FFB.
*/
const GLfloat DRAW_COLOR[] = {126.0f / 255, 143.0f / 255, 251.0f / 255, 1.0f};
/**
* Change #92D6CC.
*/
const GLfloat CHANGE_COLOR[] = {146.0f / 255, 214.0f / 255, 204.0f / 255, 1.0f};
/**
*
*/
const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = {-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f};
const EGLint ATTRIB_LIST[] = {
// 键,值。
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
// 结束。
EGL_NONE};
const EGLint CONTEXT_ATTRIBS[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
/**
*
*/
const char VERTEX_SHADER[] = "#version 300 es\n"
"layout(location = 0) in vec4 a_position;\n"
"layout(location = 1) in vec4 a_color; \n"
"out vec4 v_color; \n"
"void main() \n"
"{ \n"
" gl_Position = a_position; \n"
" v_color = a_color; \n"
"} \n";
/**
*
*/
const char FRAGMENT_SHADER[] = "#version 300 es\n"
"precision mediump float; \n"
"in vec4 v_color; \n"
"out vec4 fragColor; \n"
"void main() \n"
"{ \n"
" fragColor = v_color; \n"
"} \n";
// [End egl_const_h]
#endif // NATIVEXCOMPONENT_EGLCONST_H

View File

@ -1,646 +1,119 @@
/*
* 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.
*/
#include "EGLCore.h" #include "EGLCore.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
#include <GLES3/gl3.h>
#include <cmath>
#include <cstdio> #include <cstdio>
#include <hilog/log.h> #include <cstring>
#include "common.h"
namespace NativeOpenCAX { namespace NativeOpenCAX {
namespace {
constexpr int32_t NUM_4 = 4;
/**
* Vertex shader.
*/
const char VERTEX_SHADER[] = "#version 300 es\n"
"layout(location = 0) in vec4 a_position;\n"
"layout(location = 1) in vec4 a_color; \n"
"out vec4 v_color; \n"
"void main() \n"
"{ \n"
" gl_Position = a_position; \n"
" v_color = a_color; \n"
"} \n";
/** EGLCore::EGLCore()
* Fragment shader. : eglDisplay_(EGL_NO_DISPLAY),
*/ eglContext_(EGL_NO_CONTEXT),
const char FRAGMENT_SHADER[] = "#version 300 es\n" eglSurface_(EGL_NO_SURFACE),
"precision mediump float; \n" nativeWindow_(nullptr) {}
"in vec4 v_color; \n"
"out vec4 fragColor; \n"
"void main() \n"
"{ \n"
" fragColor = v_color; \n"
"} \n";
// [Start native_color]
/**
* #f4f4f4.
*/
const GLfloat BACKGROUND_COLOR[] = {244.0f / 255, 244.0f / 255, 244.0f / 255, 1.0f};
/** EGLCore::~EGLCore() {
* #7E8FFB. destroy();
*/ }
const GLfloat DRAW_COLOR[] = {126.0f / 255, 143.0f / 255, 251.0f / 255, 1.0f};
/** bool EGLCore::init(OHNativeWindow* window) {
* #92D6CC. if (!window) {
*/ printf("Native window is null\n");
const GLfloat CHANGE_COLOR[] = {146.0f / 255, 214.0f / 255, 204.0f / 255, 1.0f};
/**
*
*/
const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = {
-1.0f, 1.0f,
1.0f, 1.0f,
1.0f, -1.0f,
-1.0f, -1.0f};
// [End native_color]
/**
* Get context parameter count.
*/
const size_t GET_CONTEXT_PARAM_CNT = 1;
/**
* Fifty percent.
*/
const float FIFTY_PERCENT = 0.5;
/**
* Pointer size.
*/
const GLint POINTER_SIZE = 2;
/**
* Triangle fan size.
*/
const GLsizei TRIANGLE_FAN_SIZE = 4;
/**
* Egl red size default.
*/
const int EGL_RED_SIZE_DEFAULT = 8;
/**
* Egl green size default.
*/
const int EGL_GREEN_SIZE_DEFAULT = 8;
/**
* Egl blue size default.
*/
const int EGL_BLUE_SIZE_DEFAULT = 8;
/**
* Egl alpha size default.
*/
const int EGL_ALPHA_SIZE_DEFAULT = 8;
/**
* Default x position.
*/
const int DEFAULT_X_POSITION = 0;
/**
* Default y position.
*/
const int DEFAULT_Y_POSITION = 0;
/**
* Gl red default.
*/
const GLfloat GL_RED_DEFAULT = 0.0;
/**
* Gl green default.
*/
const GLfloat GL_GREEN_DEFAULT = 0.0;
/**
* Gl blue default.
*/
const GLfloat GL_BLUE_DEFAULT = 0.0;
/**
* Gl alpha default.
*/
const GLfloat GL_ALPHA_DEFAULT = 1.0;
/**
* Program error.
*/
const GLuint PROGRAM_ERROR = 0;
/**
* Shape vertices size.
*/
const int SHAPE_VERTICES_SIZE = 8;
/**
* Position handle name.
*/
const char POSITION_NAME[] = "a_position";
/**
* Position error.
*/
const GLint POSITION_ERROR = -1;
/**
* Config attribute list.
*/
const EGLint ATTRIB_LIST[] = {
// Key,value.
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, EGL_RED_SIZE_DEFAULT,
EGL_GREEN_SIZE, EGL_GREEN_SIZE_DEFAULT,
EGL_BLUE_SIZE, EGL_BLUE_SIZE_DEFAULT,
EGL_ALPHA_SIZE, EGL_ALPHA_SIZE_DEFAULT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
// End.
EGL_NONE};
/**
* Context attributes.
*/
const EGLint CONTEXT_ATTRIBS[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE};
} // namespace
// [Start native_create_context_init]
bool EGLCore::EglContextInit(void* window, int width, int height)
{
// [StartExclude native_create_context_init]
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit execute");
if ((window == nullptr) || (width <= 0) || (height <= 0)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit: param error");
return false; return false;
} }
// [EndExclude native_create_context_init]
UpdateSize(width, height);
eglWindow_ = static_cast<EGLNativeWindowType>(window);
// 初始化display nativeWindow_ = window;
// 获取EGL display
eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (eglDisplay_ == EGL_NO_DISPLAY) { if (eglDisplay_ == EGL_NO_DISPLAY) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglGetDisplay: unable to get EGL display"); printf("eglGetDisplay failed\n");
return false; return false;
} }
// 初始化EGL // 初始化EGL
EGLint majorVersion; if (!eglInitialize(eglDisplay_, nullptr, nullptr)) {
EGLint minorVersion; printf("eglInitialize failed\n");
if (!eglInitialize(eglDisplay_, &majorVersion, &minorVersion)) {
OH_LOG_Print(
LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglInitialize: unable to get initialize EGL display");
return false; return false;
} }
// 选择配置 // 配置EGL
const EGLint maxConfigSize = 1; EGLint attribs[] = {
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
};
EGLint numConfigs; EGLint numConfigs;
if (!eglChooseConfig(eglDisplay_, ATTRIB_LIST, &eglConfig_, maxConfigSize, &numConfigs)) { if (!eglChooseConfig(eglDisplay_, attribs, &eglConfig_, 1, &numConfigs) || numConfigs == 0) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglChooseConfig: unable to choose configs"); printf("eglChooseConfig failed\n");
return false; return false;
} }
// 创建环境
return CreateEnvironment(); // 创建EGL surface
eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, (NativeWindowType)nativeWindow_, nullptr);
if (eglSurface_ == EGL_NO_SURFACE) {
printf("eglCreateWindowSurface failed: 0x%x\n", eglGetError());
return false;
}
// 创建EGL context
EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, contextAttribs);
if (eglContext_ == EGL_NO_CONTEXT) {
printf("eglCreateContext failed\n");
return false;
}
// 激活上下文
makeCurrent();
// 检查GL错误
GLenum glError = glGetError();
if (glError != GL_NO_ERROR) {
printf("OpenGL error after initialization: 0x%x\n", glError);
return false;
}
// 设置GL视口
glViewport(0, 0, 1280, 720); // 默认大小,实际会随窗口变化
return true;
} }
// [End native_create_context_init]
// [Start native_create_environment] void EGLCore::makeCurrent() {
bool EGLCore::CreateEnvironment()
{
// 创建Surface
if (eglWindow_ == nullptr) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglWindow_ is null");
return false;
}
eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL);
if (eglSurface_ == nullptr) {
OH_LOG_Print(
LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglCreateWindowSurface: unable to create surface");
return false;
}
// 创建context
eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, CONTEXT_ATTRIBS);
if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) { if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglMakeCurrent failed"); printf("eglMakeCurrent failed: 0x%x\n", eglGetError());
return false;
}
// 创建program
program_ = CreateProgram(VERTEX_SHADER, FRAGMENT_SHADER);
if (program_ == PROGRAM_ERROR) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "CreateProgram: unable to create program");
return false;
}
return true;
}
// [End native_create_environment]
// [Start native_background]
// 绘制背景颜色
void EGLCore::Background()
{
GLint position = PrepareDraw();
if (position == POSITION_ERROR) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background get position failed");
return;
}
if (!ExecuteDraw(position, BACKGROUND_COLOR,
BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background execute draw failed");
return;
}
if (!FinishDraw()) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background FinishDraw failed");
return;
} }
} }
// [End native_background]
// [Start native_draw]
void EGLCore::Draw(int& hasDraw)
{
flag_ = false;
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "Draw");
GLint position = PrepareDraw();
if (position == POSITION_ERROR) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw get position failed");
return;
}
// 绘制背景 bool EGLCore::swapBuffers() {
if (!ExecuteDraw(position, BACKGROUND_COLOR,
BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw background failed");
return;
}
// 将五角星分为五个四边形,计算其中一个四边形的四个顶点
GLfloat rotateX = 0;
GLfloat rotateY = FIFTY_PERCENT * height_;
GLfloat centerX = 0;
// Convert DEG(54° & 18°) to RAD
GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18);
// Convert DEG(18°) to RAD
GLfloat leftX = -rotateY * (M_PI / 180 * 18);
GLfloat leftY = 0;
// Convert DEG(18°) to RAD
GLfloat rightX = rotateY * (M_PI / 180 * 18);
GLfloat rightY = 0;
// 确定绘制四边形的顶点,使用绘制区域的百分比表示
const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_,
rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ };
if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed");
return;
}
// Convert DEG(72°) to RAD
GLfloat rad = M_PI / 180 * 72;
// Rotate four times
// 在文件egl_core.cpp中定义NUM_4的值为4
for (int i = 0; i < NUM_4; ++i) {
// 旋转得其他四个四边形的顶点
Rotate2d(centerX, centerY, &rotateX, &rotateY, rad);
Rotate2d(centerX, centerY, &leftX, &leftY, rad);
Rotate2d(centerX, centerY, &rightX, &rightY, rad);
// 确定绘制四边形的顶点,使用绘制区域的百分比表示
const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_,
rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ };
// 绘制图形
if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed");
return;
}
}
// 结束绘制
if (!FinishDraw()) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw FinishDraw failed");
return;
}
hasDraw = 1;
flag_ = true;
}
// [End native_draw]
// [Start native_change_color]
void EGLCore::ChangeColor(int& hasChangeColor)
{
if (!flag_) {
return;
}
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor");
GLint position = PrepareDraw();
if (position == POSITION_ERROR) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor get position failed");
return;
}
// 绘制背景
if (!ExecuteDraw(position, BACKGROUND_COLOR,
BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor execute draw background failed");
return;
}
// 确定绘制四边形的顶点,使用绘制区域的百分比表示
GLfloat rotateX = 0;
GLfloat rotateY = FIFTY_PERCENT * height_;
GLfloat centerX = 0;
// Convert DEG(54° & 18°) to RAD
GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18);
// Convert DEG(18°) to RAD
GLfloat leftX = -rotateY * (M_PI / 180 * 18);
GLfloat leftY = 0;
// Convert DEG(18°) to RAD
GLfloat rightX = rotateY * (M_PI / 180 * 18);
GLfloat rightY = 0;
// 确定绘制四边形的顶点,使用绘制区域的百分比表示
const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_,
rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ };
// 使用新的颜色绘制
if (!ExecuteDrawNewStar(0, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed");
return;
}
// Convert DEG(72°) to RAD
GLfloat rad = M_PI / 180 * 72;
// Rotate four times
// 在文件egl_core.cpp中定义NUM_4的值为4
for (int i = 0; i < NUM_4; ++i) {
// 旋转得其他四个四边形的顶点
Rotate2d(centerX, centerY, &rotateX, &rotateY, rad);
Rotate2d(centerX, centerY, &leftX, &leftY, rad);
Rotate2d(centerX, centerY, &rightX, &rightY, rad);
// 确定绘制四边形的顶点,使用绘制区域的百分比表示
const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_,
rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ };
// 使用新的颜色绘制
if (!ExecuteDrawNewStar(position, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed");
return;
}
}
// 结束绘制
if (!FinishDraw()) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor FinishDraw failed");
}
hasChangeColor = 1;
}
// [StartExclude native_change_color]
// [Start native_prepare_draw]
// 绘前准备获取position创建成功时position值从0开始
GLint EGLCore::PrepareDraw()
{
if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) ||
(!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "PrepareDraw: param error");
return POSITION_ERROR;
}
// 该gl函数没有返回值。
glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_);
glClearColor(GL_RED_DEFAULT, GL_GREEN_DEFAULT, GL_BLUE_DEFAULT, GL_ALPHA_DEFAULT);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program_);
return glGetAttribLocation(program_, POSITION_NAME);
}
// [End native_prepare_draw]
// [Start native_execute_draw]
// 依据传入参数在指定区域绘制指定颜色
bool EGLCore::ExecuteDraw(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize)
{
if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error");
return false;
}
// 该gl函数没有返回值。
glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices);
glEnableVertexAttribArray(position);
glVertexAttrib4fv(1, color);
glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE);
glDisableVertexAttribArray(position);
return true;
}
// [End native_execute_draw]
bool EGLCore::ExecuteDrawStar(
GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize)
{
if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error");
return false;
}
// The gl function has no return value.
glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices);
glVertexAttribPointer(1, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, color);
glEnableVertexAttribArray(position);
glEnableVertexAttribArray(1);
glVertexAttrib4fv(1, color);
glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE);
glDisableVertexAttribArray(position);
glDisableVertexAttribArray(1);
return true;
}
// [EndExclude native_change_color]
bool EGLCore::ExecuteDrawNewStar(
GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize)
{
if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error");
return false;
}
// 该gl函数没有返回值。
glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices);
glEnableVertexAttribArray(position);
glVertexAttrib4fv(1, color);
glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE);
glDisableVertexAttribArray(position);
return true;
}
// [End native_change_color]
void EGLCore::Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat* rotateX, GLfloat* rotateY, GLfloat theta)
{
GLfloat tempX = cos(theta) * (*rotateX - centerX) - sin(theta) * (*rotateY - centerY);
GLfloat tempY = sin(theta) * (*rotateX - centerX) + cos(theta) * (*rotateY - centerY);
*rotateX = tempX + centerX;
*rotateY = tempY + centerY;
}
// [Start native_finish_draw]
// 结束绘制操作
bool EGLCore::FinishDraw()
{
// 强制刷新缓冲
glFlush();
glFinish();
return eglSwapBuffers(eglDisplay_, eglSurface_); return eglSwapBuffers(eglDisplay_, eglSurface_);
} }
// [End native_finish_draw]
// [Start native_load_shader]
GLuint EGLCore::LoadShader(GLenum type, const char* shaderSrc)
{
if ((type <= 0) || (shaderSrc == nullptr)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader type or shaderSrc error");
return PROGRAM_ERROR;
}
GLuint shader = glCreateShader(type); void EGLCore::destroy() {
if (shader == 0) { if (eglDisplay_ != EGL_NO_DISPLAY) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader unable to load shader"); if (eglContext_ != EGL_NO_CONTEXT) {
return PROGRAM_ERROR; eglDestroyContext(eglDisplay_, eglContext_);
} eglContext_ = EGL_NO_CONTEXT;
}
// 该gl函数没有返回值。 if (eglSurface_ != EGL_NO_SURFACE) {
glShaderSource(shader, 1, &shaderSrc, nullptr); eglDestroySurface(eglDisplay_, eglSurface_);
glCompileShader(shader); eglSurface_ = EGL_NO_SURFACE;
}
GLint compiled; eglTerminate(eglDisplay_);
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); eglDisplay_ = EGL_NO_DISPLAY;
if (compiled != 0) {
return shader;
}
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen <= 1) {
glDeleteShader(shader);
return PROGRAM_ERROR;
}
char* infoLog = (char*)malloc(sizeof(char) * (infoLen + 1));
if (infoLog != nullptr) {
memset(infoLog, 0, infoLen + 1);
glGetShaderInfoLog(shader, infoLen, nullptr, infoLog);
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCompileShader error = %s", infoLog);
free(infoLog);
infoLog = nullptr;
}
glDeleteShader(shader);
return PROGRAM_ERROR;
}
// [End native_load_shader]
// [Start native_create_program]
GLuint EGLCore::CreateProgram(const char* vertexShader, const char* fragShader)
{
if ((vertexShader == nullptr) || (fragShader == nullptr)) {
OH_LOG_Print(
LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram: vertexShader or fragShader is null");
return PROGRAM_ERROR;
}
GLuint vertex = LoadShader(GL_VERTEX_SHADER, vertexShader);
if (vertex == PROGRAM_ERROR) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram vertex error");
return PROGRAM_ERROR;
}
GLuint fragment = LoadShader(GL_FRAGMENT_SHADER, fragShader);
if (fragment == PROGRAM_ERROR) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram fragment error");
return PROGRAM_ERROR;
}
GLuint program = glCreateProgram();
if (program == PROGRAM_ERROR) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram program error");
glDeleteShader(vertex);
glDeleteShader(fragment);
return PROGRAM_ERROR;
}
// 该gl函数没有返回值。
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (linked != 0) {
glDeleteShader(vertex);
glDeleteShader(fragment);
return program;
}
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram linked error");
GLint infoLen = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* infoLog = (char*)malloc(sizeof(char) * (infoLen + 1));
memset(infoLog, 0, infoLen + 1);
glGetProgramInfoLog(program, infoLen, nullptr, infoLog);
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glLinkProgram error = %s", infoLog);
free(infoLog);
infoLog = nullptr;
}
glDeleteShader(vertex);
glDeleteShader(fragment);
glDeleteProgram(program);
return PROGRAM_ERROR;
}
// [End native_create_program]
// [Start native_update_size]
void EGLCore::UpdateSize(int width, int height)
{
// width_和height_在头文件中定义
width_ = width;
height_ = height;
if (width_ > 0) {
widthPercent_ = FIFTY_PERCENT * height_ / width_;
} }
} }
// [End native_update_size]
// [Start native_release] } // namespace NativeOpenCAX
void EGLCore::Release()
{
// 释放Surface
if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (!eglDestroySurface(eglDisplay_, eglSurface_))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroySurface failed");
}
// 释放context
if ((eglDisplay_ == nullptr) || (eglContext_ == nullptr) || (!eglDestroyContext(eglDisplay_, eglContext_))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroyContext failed");
}
// 释放display
if ((eglDisplay_ == nullptr) || (!eglTerminate(eglDisplay_))) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglTerminate failed");
}
}
// [End native_release]
} // namespace NativeXComponentSample

View File

@ -12,49 +12,30 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#ifndef NATIVE_XCOMPONENT_EGL_CORE_H #ifndef EGLCORE_H
#define NATIVE_XCOMPONENT_EGL_CORE_H #define EGLCORE_H
#include <EGL/egl.h> #include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h> #include <GLES3/gl3.h>
#include "string" #include <native_window/external_window.h>
namespace NativeOpenCAX { namespace NativeOpenCAX {
class EGLCore { class EGLCore {
public: public:
explicit EGLCore() {} EGLCore();
~EGLCore() {} ~EGLCore();
bool EglContextInit(void* window, int width, int height);
bool CreateEnvironment(); bool init(OHNativeWindow* window);
void Draw(int& hasDraw); void makeCurrent();
void Background(); bool swapBuffers();
void ChangeColor(int& hasChangeColor); void destroy();
void Release(); EGLSurface getSurface() const { return eglSurface_; }
void UpdateSize(int width, int height);
private: private:
GLuint LoadShader(GLenum type, const char* shaderSrc); EGLDisplay eglDisplay_;
GLuint CreateProgram(const char* vertexShader, const char* fragShader); EGLContext eglContext_;
GLint PrepareDraw(); EGLSurface eglSurface_;
bool ExecuteDraw(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize); EGLConfig eglConfig_;
bool ExecuteDrawStar(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize); OHNativeWindow* nativeWindow_;
bool ExecuteDrawNewStar(GLint position, const GLfloat* color,
const GLfloat shapeVertices[], unsigned long vertSize);
void Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat* rotateX, GLfloat* rotateY, GLfloat theta);
bool FinishDraw();
private:
EGLNativeWindowType eglWindow_;
EGLDisplay eglDisplay_ = EGL_NO_DISPLAY;
EGLConfig eglConfig_ = EGL_NO_CONFIG_KHR;
EGLSurface eglSurface_ = EGL_NO_SURFACE;
EGLContext eglContext_ = EGL_NO_CONTEXT;
GLuint program_;
bool flag_ = false;
int width_;
int height_;
GLfloat widthPercent_;
}; };
} // namespace NativeXComponentSample } // namespace NativeOpenCAX
#endif // NATIVE_XCOMPONENT_EGL_CORE_H #endif // EGLCORE_H

View File

@ -23,7 +23,7 @@
#include "arkui/native_node_napi.h" #include "arkui/native_node_napi.h"
#include "arkui/native_interface.h" #include "arkui/native_interface.h"
#include "common.h" #include "common.h"
#include <map>
#define COLUMN_MARGIN 10 #define COLUMN_MARGIN 10
#define XC_WIDTH 800 #define XC_WIDTH 800
#define XC_HEIGHT 600 #define XC_HEIGHT 600
@ -44,13 +44,17 @@ OH_NativeXComponent_Callback NativeManager::callback_;
ArkUI_NodeHandle xc; ArkUI_NodeHandle xc;
int32_t NativeManager::hasDraw_ = 0; int32_t NativeManager::hasDraw_ = 0;
int32_t NativeManager::hasChangeColor_ = 0; int32_t NativeManager::hasChangeColor_ = 0;
static std::map<int64_t, std::shared_ptr<NativeRenderThread>> renderThreadMap;
static std::mutex mapMutex;
NativeManager::~NativeManager() { NativeManager::~NativeManager() {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "~NativeManager"); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "~NativeManager");
nativeXComponentMap_.clear(); nativeXComponentMap_.clear();
if (eglcore_ != nullptr) { int64_t id = 0;
delete eglcore_; std::lock_guard<std::mutex> lock(mapMutex);
eglcore_ = nullptr; if (renderThreadMap.find(id) != renderThreadMap.end()) {
renderThreadMap[id]->stop();
renderThreadMap.erase(id);
} }
for (auto iter = pluginManagerMap_.begin(); iter != pluginManagerMap_.end(); ++iter) { for (auto iter = pluginManagerMap_.begin(); iter != pluginManagerMap_.end(); ++iter) {
@ -62,38 +66,38 @@ NativeManager::~NativeManager() {
pluginManagerMap_.clear(); pluginManagerMap_.clear();
} }
// Surface回调事件 // Surface回调事件
void OnSurfaceCreatedNative(OH_ArkUI_SurfaceHolder *holder) { //void OnSurfaceCreatedNative(OH_ArkUI_SurfaceHolder *holder) {
auto window = OH_ArkUI_XComponent_GetNativeWindow(holder); // 获取native window // auto window = OH_ArkUI_XComponent_GetNativeWindow(holder); // 获取native window
auto eglCore = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder)); // auto eglCore = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
eglCore->EglContextInit(window, 800, 600); // eglCore->EglContextInit(window, 800, 600);
} //}
void OnSurfaceChangedNative(OH_ArkUI_SurfaceHolder *holder, uint64_t width, uint64_t height) { //void OnSurfaceChangedNative(OH_ArkUI_SurfaceHolder *holder, uint64_t width, uint64_t height) {
EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder)); // EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
render->UpdateSize(width, height); // 设置绘制区域大小 // render->UpdateSize(width, height); // 设置绘制区域大小
render->Draw(NativeManager::hasDraw_); // 绘制五角星 // //render->Draw(NativeManager::hasDraw_); // 绘制五角星
} //}
void OnSurfaceDestroyedNative(OH_ArkUI_SurfaceHolder *holder) { //void OnSurfaceDestroyedNative(OH_ArkUI_SurfaceHolder *holder) {
OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onBind", "on destroyed"); // OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onBind", "on destroyed");
EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder)); // EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
render->Release(); // 销毁eglSurface相关资源 // render->Release(); // 销毁eglSurface相关资源
} //}
void OnSurfaceShowNative(OH_ArkUI_SurfaceHolder *holder) { //void OnSurfaceShowNative(OH_ArkUI_SurfaceHolder *holder) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface show"); // OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface show");
} //}
void OnSurfaceHideNative(OH_ArkUI_SurfaceHolder *holder) { //void OnSurfaceHideNative(OH_ArkUI_SurfaceHolder *holder) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface hide"); // OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface hide");
} //}
void OnFrameCallbackNative(ArkUI_NodeHandle node, uint64_t timestamp, uint64_t targetTimestamp) { //void OnFrameCallbackNative(ArkUI_NodeHandle node, uint64_t timestamp, uint64_t targetTimestamp) {
if (!NativeManager::surfaceHolderMap_.count(node)) { // if (!NativeManager::surfaceHolderMap_.count(node)) {
return; // return;
} // }
static uint64_t count = 0; // static uint64_t count = 0;
count++; // count++;
// 在头文件plugin_manager.h中定义FRAME_COUNT的值为50 // // 在头文件plugin_manager.h中定义FRAME_COUNT的值为50
if (count % FRAME_COUNT == 0) { // if (count % FRAME_COUNT == 0) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "OnFrameCallback count = %{public}ld", count); // OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "OnFrameCallback count = %{public}ld", count);
} // }
} //}
void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) { void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) {
// [StartExclude plugin_on_surface_created] // [StartExclude plugin_on_surface_created]
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB"); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB");
@ -144,79 +148,38 @@ void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) {
auto *pluginManger = NativeManager::GetInstance(); auto *pluginManger = NativeManager::GetInstance();
pluginManger->OnSurfaceDestroyed(component, window); pluginManger->OnSurfaceDestroyed(component, window);
} }
void DispatchTouchEventCB(OH_NativeXComponent *component, void *window) {
// [StartExclude plugin_dispatch_touch_event]
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB");
int32_t ret;
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
return;
}
std::string id(idStr);
// [EndExclude plugin_dispatch_touch_event]
auto *pluginManger = NativeManager::GetInstance();
pluginManger->DispatchTouchEvent(component, window);
}
//NativeManager回调 //NativeManager回调
void NativeManager::OnSurfaceCreated(OH_NativeXComponent *component, void *window) { void NativeManager::OnSurfaceCreated(OH_NativeXComponent *component, void *window) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceCreated"); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceCreated");
int32_t ret; OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; int64_t id = 0;
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; std::lock_guard<std::mutex> lock(mapMutex);
ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); if (renderThreadMap.find(id) == renderThreadMap.end()) {
ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_); auto renderThread = std::make_shared<NativeRenderThread>();
if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { renderThreadMap[id] = renderThread;
eglcore_->EglContextInit(window, width_, height_); renderThread->start(reinterpret_cast<OHNativeWindow*>(window));
eglcore_->Background();
} }
} }
void NativeManager::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) { void NativeManager::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceDestroyed"); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceDestroyed");
} int64_t id = 0;
void NativeManager::DispatchTouchEvent(OH_NativeXComponent *component, void *window) { {
int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_); std::lock_guard<std::mutex> lock(mapMutex);
if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { if (renderThreadMap.find(id) != renderThreadMap.end()) {
float tiltX = 2.2; renderThreadMap[id]->stop();
float tiltY = 2.2; renderThreadMap.erase(id);
OH_NativeXComponent_TouchPointToolType toolType =
OH_NativeXComponent_TouchPointToolType::OH_NATIVEXCOMPONENT_TOOL_TYPE_LENS;
OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType);
OH_NativeXComponent_GetTouchPointTiltX(component, 0, &tiltX);
OH_NativeXComponent_GetTouchPointTiltY(component, 0, &tiltY);
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native",
"Touch Info : x=%{public}f, y=%{public}f screenx=%{public}f, screeny=%{public}f,"
"type=%{public}d, force=%{public}f, tiltX=%{public}f, tiltY=%{public}f, toolType=%{public}d",
touchEvent_.x, touchEvent_.y, touchEvent_.screenX, touchEvent_.screenY, touchEvent_.type,
touchEvent_.force, tiltX, tiltY, toolType);
if (touchEvent_.type == OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_UP) {
eglcore_->ChangeColor(hasChangeColor_);
}
} else {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "touch fail");
}
int32_t size = 0;
OH_NativeXComponent_HistoricalPoint *points = nullptr;
if (OH_NativeXComponent_GetHistoricalPoints(component, window, &size, &points) ==
OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponent_Native", "HistoricalPoints size=%{public}d",
size);
for (auto i = 0; i < size; i++) {
auto point = points[i];
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponent_Native",
"HistoricalPoint %{public}d Info : id=%{public}d, x=%{public}f, y=%{public}f, "
"type=%{public}d, timeStamp=%{public}lld, sourceTool=%{public}d",
i, point.id, point.x, point.y, point.type, point.timeStamp, point.sourceTool);
} }
} }
} }
void NativeManager::OnSurfaceChanged(OH_NativeXComponent *component, void *window) { void NativeManager::OnSurfaceChanged(OH_NativeXComponent *component, void *window) {
int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_); OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", int64_t id = 0;
"OnSurfaceChanged ret=%{public}d width=%{public}lu, height=%{public}lu", ret, width_, height_); {
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) != renderThreadMap.end()) {
renderThreadMap[id]->resizeWindow(width_, height_);
}
}
} }
void onEvent(ArkUI_NodeEvent *event) { void onEvent(ArkUI_NodeEvent *event) {
auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); // 获取组件事件类型 auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); // 获取组件事件类型
@ -225,7 +188,6 @@ void onEvent(ArkUI_NodeEvent *event) {
ArkUI_NodeHandle handle = OH_ArkUI_NodeEvent_GetNodeHandle(event); // 获取触发该事件的组件对象 ArkUI_NodeHandle handle = OH_ArkUI_NodeEvent_GetNodeHandle(event); // 获取触发该事件的组件对象
auto holder = NativeManager::surfaceHolderMap_[handle]; auto holder = NativeManager::surfaceHolderMap_[handle];
EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder)); EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
render->Draw(NativeManager::hasDraw_); // 绘制五角星
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on touch"); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on touch");
} }
} }
@ -237,35 +199,11 @@ static std::string value2String(napi_env env, napi_value value) {
napi_get_value_string_utf8(env, value, &valueString[0], stringSize + 1, &stringSize); napi_get_value_string_utf8(env, value, &valueString[0], stringSize + 1, &stringSize);
return valueString; return valueString;
} }
napi_value NativeManager::NapiDrawPattern(napi_env env, napi_callback_info info) {
// [StartExclude plugin_draw_pattern]
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeManager", "NapiDrawPattern");
if ((env == nullptr) || (info == nullptr)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "NapiDrawPattern: env or info is null");
return nullptr;
}
// [EndExclude plugin_draw_pattern]
// 获取环境变量参数
napi_value thisArg;
if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "NapiDrawPattern: napi_get_cb_info fail");
return nullptr;
}
auto *pluginManger = NativeManager::GetInstance();
// 调用绘制方法
pluginManger->eglcore_->Draw(hasDraw_);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeManager", "render->eglCore_->Draw() executed");
return nullptr;
}
// XComponent回调事件 // XComponent回调事件
NativeManager::NativeManager() { NativeManager::NativeManager() {
eglcore_ = new EGLCore();
callback_.OnSurfaceCreated = OnSurfaceCreatedCB; callback_.OnSurfaceCreated = OnSurfaceCreatedCB;
callback_.OnSurfaceChanged = OnSurfaceChangedCB; callback_.OnSurfaceChanged = OnSurfaceChangedCB;
callback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB; callback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
callback_.DispatchTouchEvent = DispatchTouchEventCB;
} }
// 创建节点组件 // 创建节点组件
ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) { ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) {
@ -419,5 +357,18 @@ napi_value NativeManager::SetNeedSoftKeyboard(napi_env env, napi_callback_info i
OH_ArkUI_XComponent_SetNeedSoftKeyboard(node, needSoftKeyboard); // 设置是否需要软键盘 OH_ArkUI_XComponent_SetNeedSoftKeyboard(node, needSoftKeyboard); // 设置是否需要软键盘
return nullptr; return nullptr;
} }
napi_value NativeManager::NapiLoadModel(napi_env env, napi_callback_info info) {
size_t argc = 1;
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));
}
}
return nullptr;
}
} // namespace NativeOpenCAX } // namespace NativeOpenCAX

View File

@ -25,7 +25,7 @@
#include "EGLCore.h" #include "EGLCore.h"
#include "arkui/native_node.h" #include "arkui/native_node.h"
#include "arkui/native_node_napi.h" #include "arkui/native_node_napi.h"
#include "NativeRenderThread.h"
namespace NativeOpenCAX { namespace NativeOpenCAX {
@ -47,9 +47,9 @@ public:
return &NativeManager::pluginManager_; return &NativeManager::pluginManager_;
} }
static napi_value createNativeNode(napi_env env, napi_callback_info info); static napi_value createNativeNode(napi_env env, napi_callback_info info);
static napi_value NapiDrawPattern(napi_env env, napi_callback_info info);
static napi_value SetFrameRate(napi_env env, napi_callback_info info); static napi_value SetFrameRate(napi_env env, napi_callback_info info);
static napi_value SetNeedSoftKeyboard(napi_env env, napi_callback_info info); static napi_value SetNeedSoftKeyboard(napi_env env, napi_callback_info info);
static napi_value NapiLoadModel(napi_env env, napi_callback_info info);
// CApi XComponent // CApi XComponent
void OnSurfaceChanged(OH_NativeXComponent* component, void* window); void OnSurfaceChanged(OH_NativeXComponent* component, void* window);
void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window); void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window);
@ -61,10 +61,10 @@ private:
std::unordered_map<std::string, NativeManager*> pluginManagerMap_; std::unordered_map<std::string, NativeManager*> pluginManagerMap_;
public: public:
// [StartExclude plugin_manager_h_part] // [StartExclude plugin_manager_h_part]
EGLCore *eglcore_;
uint64_t width_; uint64_t width_;
uint64_t height_; uint64_t height_;
OH_NativeXComponent_TouchEvent touchEvent_; OH_NativeXComponent_TouchEvent touchEvent_;
std::string modelPath_;
static int32_t hasDraw_; static int32_t hasDraw_;
static int32_t hasChangeColor_; static int32_t hasChangeColor_;
static std::unordered_map<std::string, ArkUI_NodeHandle> nodeHandleMap_; static std::unordered_map<std::string, ArkUI_NodeHandle> nodeHandleMap_;

View File

@ -0,0 +1,279 @@
#include "NativeRender.h"
#include <cstdio>
#include <cmath>
#include <OSD_Environment.hxx>
#include <AIS_InteractiveObject.hxx>
#include <Prs3d_Drawer.hxx>
#include <Prs3d_ShadingAspect.hxx>
#include <Graphic3d_MaterialAspect.hxx>
#include <Graphic3d_NameOfMaterial.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <Graphic3d_TextureEnv.hxx>
#include <V3d_TypeOfOrientation.hxx>
#include <Aspect_TypeOfTriedronPosition.hxx>
namespace NativeOpenCAX {
NativeRender::NativeRender()
: rotationX_(0.0f),
rotationY_(0.0f),
zoomLevel_(1.0f),
width_(0),
height_(0),
clearColor_(Quantity_NOC_BLACK),
translationX_(0.0f),
translationY_(0.0f)
{
setupViewer();
setupContext();
setupView();
}
NativeRender::~NativeRender() {
shapes_.clear();
}
bool NativeRender::init(int width, int height) {
width_ = width;
height_ = height;
if (view_.IsNull()) {
return false;
}
view_->SetBackgroundColor(clearColor_);
view_->MustBeResized();
view_->Redraw();
return true;
}
void NativeRender::setupViewer() {
Handle(Aspect_DisplayConnection) displayConnection;
// 创建图形驱动
static Handle(OpenGl_GraphicDriver) graphicDriver;
if (graphicDriver.IsNull()) {
graphicDriver = new OpenGl_GraphicDriver(displayConnection, Standard_False);
graphicDriver->ChangeOptions().buffersNoSwap = Standard_True;
}
graphicDriver_ = graphicDriver;
// 创建V3d_Viewer
viewer_ = new V3d_Viewer(graphicDriver_);
viewer_->SetDefaultLights();
viewer_->SetLightOn();
}
void NativeRender::setupContext() {
context_ = new AIS_InteractiveContext(viewer_);
context_->SetDisplayMode(AIS_Shaded, Standard_False); // 默认使用着色模式
}
void NativeRender::setupView() {
view_ = viewer_->CreateView();
// 设置渲染参数
view_->ChangeRenderingParams().Method = Graphic3d_RM_RASTERIZATION;
view_->ChangeRenderingParams().IsShadowEnabled = Standard_False;
view_->ChangeRenderingParams().IsReflectionEnabled = Standard_False;
view_->ChangeRenderingParams().IsAntialiasingEnabled = Standard_True;
view_->ChangeRenderingParams().Resolution = 2;
// 设置背景渐变
view_->SetBgGradientColors(
Quantity_Color(Quantity_NOC_GRAY),
Quantity_Color(Quantity_NOC_BLACK),
Aspect_GFM_VER, // 垂直渐变
Standard_False
);
// 设置默认相机位置
view_->SetProj(V3d_XposYnegZpos);
// 设置相机参数
Handle(Graphic3d_Camera) camera = view_->Camera();
camera->SetFOVy(45.0); // 使用正确的FOV设置API
camera->SetZRange(1.0, 10000.0);
}
bool NativeRender::loadModel(const std::string& filePath) {
// 清除现有模型
for (auto& shape : shapes_) {
context_->Remove(shape, Standard_False);
}
shapes_.clear();
// 加载STEP文件
STEPControl_Reader reader;
IFSelect_ReturnStatus status = reader.ReadFile(filePath.c_str());
if (status != IFSelect_RetDone) {
printf("Error: Failed to read STEP file: %s\n", filePath.c_str());
loadDefaultModel();
return false;
}
// 将文件内容转换为OCCT形状
reader.TransferRoots();
int numShapes = reader.NbShapes();
if (numShapes <= 0) {
printf("Error: No shapes found in STEP file\n");
loadDefaultModel();
return false;
}
// 加载所有形状
for (Standard_Integer i = 1; i <= numShapes; i++) {
TopoDS_Shape shape = reader.Shape(i);
if (!shape.IsNull()) {
Handle(AIS_Shape) aisShape = new AIS_Shape(shape);
// 设置材质
Handle(Prs3d_Drawer) drawer = aisShape->Attributes();
Handle(Prs3d_ShadingAspect) shadingAspect = new Prs3d_ShadingAspect();
// 随机颜色
int colorIndex = i % 7;
Quantity_Color color;
switch (colorIndex) {
case 0: color = Quantity_NOC_RED; break;
case 1: color = Quantity_NOC_GREEN; break;
case 2: color = Quantity_NOC_BLUE1; break;
case 3: color = Quantity_NOC_YELLOW; break;
case 4: color = Quantity_NOC_MAGENTA1; break;
case 5: color = Quantity_NOC_CYAN1; break;
case 6: color = Quantity_NOC_ORANGE; break;
default: color = Quantity_NOC_WHITE;
}
shadingAspect->SetColor(color);
shadingAspect->SetMaterial(Graphic3d_NOM_PLASTIC);
drawer->SetShadingAspect(shadingAspect);
context_->Display(aisShape, Standard_True);
shapes_.push_back(aisShape);
}
}
// 调整相机到合适位置
view_->FitAll(0.05, Standard_True);
view_->ZFitAll();
printf("Successfully loaded STEP file with %d shapes\n", numShapes);
return true;
}
void NativeRender::loadDefaultModel() {
// 创建一个默认的3D立方体
TopoDS_Shape box = BRepPrimAPI_MakeBox(10.0, 10.0, 10.0).Shape();
Handle(AIS_Shape) aisBox = new AIS_Shape(box);
// 设置材质和颜色
Handle(Prs3d_Drawer) drawer = aisBox->Attributes();
Handle(Prs3d_ShadingAspect) shadingAspect = new Prs3d_ShadingAspect();
shadingAspect->SetColor(Quantity_NOC_RED);
shadingAspect->SetMaterial(Graphic3d_NOM_PLASTIC);
drawer->SetShadingAspect(shadingAspect);
context_->Display(aisBox, Standard_True);
shapes_.push_back(aisBox);
// 创建一个球体
TopoDS_Shape sphere = BRepPrimAPI_MakeSphere(gp_Pnt(20.0, 0.0, 0.0), 5.0).Shape();
Handle(AIS_Shape) aisSphere = new AIS_Shape(sphere);
shadingAspect = new Prs3d_ShadingAspect();
shadingAspect->SetColor(Quantity_NOC_BLUE1);
shadingAspect->SetMaterial(Graphic3d_NOM_PLASTIC);
aisSphere->Attributes()->SetShadingAspect(shadingAspect);
context_->Display(aisSphere, Standard_True);
shapes_.push_back(aisSphere);
// 创建一个圆柱体
TopoDS_Shape cylinder = BRepPrimAPI_MakeCylinder(3.0, 15.0).Shape();
Handle(AIS_Shape) aisCylinder = new AIS_Shape(cylinder);
shadingAspect = new Prs3d_ShadingAspect();
shadingAspect->SetColor(Quantity_NOC_GREEN);
shadingAspect->SetMaterial(Graphic3d_NOM_PLASTIC);
aisCylinder->Attributes()->SetShadingAspect(shadingAspect);
gp_Trsf transform;
transform.SetTranslation(gp_Vec(-15.0, -15.0, 0.0));
aisCylinder->SetLocalTransformation(transform);
context_->Display(aisCylinder, Standard_True);
shapes_.push_back(aisCylinder);
// 调整相机
view_->FitAll(0.05, Standard_True);
view_->ZFitAll();
printf("Loaded default model (cube, sphere, cylinder)\n");
}
//setTranslation
void NativeRender::setTranslation(float x, float y) {
translationX_ = x;
translationY_ = y;
}
void NativeRender::render() {
if (view_.IsNull()) {
return;
}
// 应用旋转
Handle(Graphic3d_Camera) camera = view_->Camera();
// 计算旋转
gp_Quaternion rotation;
rotation.SetEulerAngles(gp_EulerSequence::gp_Extrinsic_XYZ,
rotationX_ * M_PI / 180.0,
rotationY_ * M_PI / 180.0,
0.0);
// 计算相机位置
gp_Dir camDir(0.0, 1.0, 0.0);
gp_Vec camVec = rotation * gp_Vec(camDir);
gp_Pnt camPos = gp_Pnt(0.0, 0.0, 0.0).Translated(camVec.Reversed() * 50.0 * zoomLevel_);
// 设置相机参数
camera->SetEye(camPos);
camera->SetCenter(gp_Pnt(translationX_, translationY_, 0.0));
camera->SetUp(gp_Dir(0.0, 0.0, 1.0));
// 执行渲染
view_->Redraw();
}
void NativeRender::resize(int width, int height) {
width_ = width;
height_ = height;
if (!view_.IsNull() && nativeWindow_ != nullptr) {
view_->SetWindow(nativeWindow_);
view_->MustBeResized();
}
}
void NativeRender::setRotation(float xAngle, float yAngle) {
rotationX_ = xAngle;
rotationY_ = yAngle;
}
void NativeRender::setZoomLevel(float zoom) {
zoomLevel_ = std::max(0.1f, std::min(zoom, 5.0f)); // 限制缩放范围
}
void NativeRender::resetView() {
rotationX_ = 0.0f;
rotationY_ = 0.0f;
zoomLevel_ = 1.0f;
if (!view_.IsNull()) {
view_->SetProj(V3d_XposYnegZpos);
view_->FitAll(0.05, Standard_False);
}
}
void NativeRender::setClearColor(float r, float g, float b, float a) {
clearColor_ = Quantity_Color(r, g, b, Quantity_TOC_RGB);
if (!view_.IsNull()) {
view_->SetBackgroundColor(clearColor_);
}
}
} // namespace NativeRenderer

View File

@ -0,0 +1,64 @@
#ifndef NATIVE_RENDER_H
#define NATIVE_RENDER_H
#include <string>
#include <vector>
#include <Standard_Handle.hxx>
#include <AIS_InteractiveContext.hxx>
#include <V3d_View.hxx>
#include <V3d_Viewer.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <AIS_Shape.hxx>
#include <STEPControl_Reader.hxx>
#include <TopoDS_Shape.hxx>
#include <Graphic3d_GraphicDriver.hxx>
#include <Aspect_DisplayConnection.hxx>
#include <Message.hxx>
#include <Quantity_Color.hxx>
#include <gp_Quaternion.hxx>
#include <gp_EulerSequence.hxx>
class Aspect_Window;
class gp_Quaternion;
class Graphic3d_Camera;
namespace NativeOpenCAX {
class NativeRender {
public:
NativeRender();
~NativeRender();
bool init(int width, int height);
bool loadModel(const std::string& filePath);
void render();
void resize(int width, int height);
void setRotation(float xAngle, float yAngle);
void resetView();
void setClearColor(float r, float g, float b, float a);
void setZoomLevel(float zoom);
void setTranslation(float x, float y);
private:
void setupViewer();
void setupContext();
void setupView();
void loadDefaultModel();
Handle(OpenGl_GraphicDriver) graphicDriver_;
Handle(V3d_Viewer) viewer_;
Handle(V3d_View) view_;
Handle(AIS_InteractiveContext) context_;
std::vector<Handle(AIS_Shape)> shapes_;
float rotationX_;
float rotationY_;
float zoomLevel_;
int width_;
int height_;
float translationX_;
float translationY_;
Quantity_Color clearColor_;
Aspect_Window* nativeWindow_;
};
} // namespace NativeRender
#endif // NATIVE_RENDER_H

View File

@ -0,0 +1,190 @@
#include "NativeRenderThread.h"
#include <cstdio>
#include <unistd.h>
namespace NativeOpenCAX {
NativeRenderThread::NativeRenderThread()
: isRunning_(false),
nativeWindow_(nullptr),
windowWidth_(1280),
windowHeight_(720) {}
NativeRenderThread::~NativeRenderThread() {
stop();
}
bool NativeRenderThread::start(OHNativeWindow* window) {
if (isRunning_) {
return true;
}
nativeWindow_ = window;
// 初始化EGL
if (!eglCore_.init(nativeWindow_)) {
printf("Failed to initialize EGL\n");
return false;
}
// 初始化OCCT渲染器
if (!renderer_.init(windowWidth_, windowHeight_)) {
printf("Failed to initialize OCCT renderer\n");
eglCore_.destroy();
return false;
}
isRunning_ = true;
renderThread_ = std::thread(&NativeRenderThread::renderLoop, this);
return true;
}
void NativeRenderThread::stop() {
if (!isRunning_) {
return;
}
isRunning_ = false;
{
std::lock_guard<std::mutex> lock(commandMutex_);
commandQueue_.push(RenderCommand(CMD_EXIT));
}
commandCondition_.notify_one();
if (renderThread_.joinable()) {
renderThread_.join();
}
eglCore_.destroy();
}
void NativeRenderThread::renderLoop() {
while (isRunning_) {
RenderCommand command;
bool hasCommand = false;
{
std::unique_lock<std::mutex> lock(commandMutex_);
commandCondition_.wait_for(lock, std::chrono::milliseconds(16), [this] {
return !commandQueue_.empty();
});
if (!commandQueue_.empty()) {
command = commandQueue_.front();
commandQueue_.pop();
hasCommand = true;
}
}
if (hasCommand) {
switch (command.type) {
case CMD_LOAD_MODEL:
renderer_.loadModel(command.param1);
break;
case CMD_SET_ROTATION:
renderer_.setRotation(command.param2, command.param3);
break;
case CMD_SET_TRANSLATION:
renderer_.setTranslation(command.param2, command.param3);
break;
case CMD_RESET_VIEW:
renderer_.resetView();
break;
case CMD_SET_CLEAR_COLOR:
renderer_.setClearColor(command.param2, command.param3, command.param4, command.param5);
break;
case CMD_RESIZE:
windowWidth_ = static_cast<int>(command.param2);
windowHeight_ = static_cast<int>(command.param3);
renderer_.resize(windowWidth_, windowHeight_);
break;
case CMD_EXIT:
isRunning_ = false;
break;
}
}
if (!isRunning_) {
break;
}
// 渲染
eglCore_.makeCurrent();
renderer_.render();
eglCore_.swapBuffers();
// 调用渲染完成回调
Callback callback;
{
std::lock_guard<std::mutex> lock(callbackMutex_);
callback = renderCompleteCallback_;
}
if (callback) {
callback();
}
// 控制帧率
usleep(16000); // ~60 FPS
}
}
void NativeRenderThread::loadModel(const std::string& filePath) {
std::lock_guard<std::mutex> lock(commandMutex_);
RenderCommand cmd(CMD_LOAD_MODEL);
cmd.param1 = filePath;
commandQueue_.push(cmd);
commandCondition_.notify_one();
}
void NativeRenderThread::setRotation(float xAngle, float yAngle) {
std::lock_guard<std::mutex> lock(commandMutex_);
RenderCommand cmd(CMD_SET_ROTATION);
cmd.param2 = xAngle;
cmd.param3 = yAngle;
commandQueue_.push(cmd);
commandCondition_.notify_one();
}
void NativeRenderThread::setTranslation(float x, float y) {
std::lock_guard<std::mutex> lock(commandMutex_);
RenderCommand cmd(CMD_SET_TRANSLATION);
cmd.param2 = x;
cmd.param3 = y;
commandQueue_.push(cmd);
commandCondition_.notify_one();
}
void NativeRenderThread::resetView() {
std::lock_guard<std::mutex> lock(commandMutex_);
commandQueue_.push(RenderCommand(CMD_RESET_VIEW));
commandCondition_.notify_one();
}
void NativeRenderThread::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;
cmd.param3 = g;
cmd.param4 = b;
cmd.param5 = a;
commandQueue_.push(cmd);
commandCondition_.notify_one();
}
void NativeRenderThread::resizeWindow(int width, int height) {
std::lock_guard<std::mutex> lock(commandMutex_);
RenderCommand cmd(CMD_RESIZE);
cmd.param2 = static_cast<float>(width);
cmd.param3 = static_cast<float>(height);
commandQueue_.push(cmd);
commandCondition_.notify_one();
}
void NativeRenderThread::registerRenderCompleteCallback(Callback callback) {
std::lock_guard<std::mutex> lock(callbackMutex_);
renderCompleteCallback_ = callback;
}
} // namespace OCCTRenderer

View File

@ -0,0 +1,73 @@
#ifndef NATIVE_RENDER_THREAD_H
#define NATIVE_RENDER_THREAD_H
#include <thread>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <functional>
#include "EGLCore.h"
#include "NativeRender.h"
namespace NativeOpenCAX {
class NativeRenderThread {
public:
NativeRenderThread();
~NativeRenderThread();
bool start(OHNativeWindow* window);
void stop();
void loadModel(const std::string& filePath);
void setRotation(float xAngle, float yAngle);
void setTranslation(float x, float y);
void resetView();
void setClearColor(float r, float g, float b, float a);
void resizeWindow(int width, int height);
using Callback = std::function<void()>;
void registerRenderCompleteCallback(Callback callback);
private:
void renderLoop();
std::thread renderThread_;
std::atomic<bool> isRunning_;
OHNativeWindow* nativeWindow_;
EGLCore eglCore_;
NativeRender renderer_;
std::mutex commandMutex_;
std::condition_variable commandCondition_;
enum CommandType {
CMD_LOAD_MODEL,
CMD_SET_ROTATION,
CMD_SET_TRANSLATION,
CMD_RESET_VIEW,
CMD_SET_CLEAR_COLOR,
CMD_RESIZE,
CMD_EXIT
};
struct RenderCommand {
CommandType type;
std::string param1; // For file path
float param2, param3, param4, param5;
RenderCommand() : type(CMD_EXIT), param1(""), param2(0.0f), param3(0.0f), param4(0.0f), param5(0.0f) {}
RenderCommand(CommandType t) : type(t), param1(""), param2(0), param3(0), param4(0), param5(0) {}
};
std::queue<RenderCommand> commandQueue_;
std::mutex callbackMutex_;
Callback renderCompleteCallback_;
int windowWidth_;
int windowHeight_;
};
} // namespace NaitveRenderThread
#endif //NATIVE_RENDER_THREAD_H

View File

@ -29,6 +29,7 @@ static napi_value NativeLoadSoTest(napi_env env, napi_callback_info info)
return sum; return sum;
} }
namespace NativeOpenCAX { namespace NativeOpenCAX {
EXTERN_C_START EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) { static napi_value Init(napi_env env, napi_value exports) {
@ -40,7 +41,7 @@ static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = { napi_property_descriptor desc[] = {
// [StartExclude napi_init_part] // [StartExclude napi_init_part]
{"createNativeNode", nullptr, NativeManager::createNativeNode, nullptr, nullptr, nullptr,napi_default, nullptr }, {"createNativeNode", nullptr, NativeManager::createNativeNode, nullptr, nullptr, nullptr,napi_default, nullptr },
{"drawPattern", nullptr, NativeManager::NapiDrawPattern, nullptr, nullptr,nullptr, napi_default, nullptr}, {"loadModel", nullptr, NativeManager::NapiLoadModel, nullptr, nullptr, nullptr, napi_default, nullptr},
{"setFrameRate", nullptr, NativeManager::SetFrameRate, nullptr, nullptr, nullptr, napi_default, nullptr}, {"setFrameRate", nullptr, NativeManager::SetFrameRate, nullptr, nullptr, nullptr, napi_default, nullptr},
{"setNeedSoftKeyboard", nullptr, NativeManager::SetNeedSoftKeyboard, nullptr, nullptr, nullptr, napi_default,nullptr}, {"setNeedSoftKeyboard", nullptr, NativeManager::SetNeedSoftKeyboard, nullptr, nullptr, nullptr, napi_default,nullptr},
{"nativeLoadTest", nullptr, NativeLoadSoTest, nullptr, nullptr, nullptr, napi_default, nullptr}, {"nativeLoadTest", nullptr, NativeLoadSoTest, nullptr, nullptr, nullptr, napi_default, nullptr},

View File

@ -1,24 +1,6 @@
/* export interface NativeXOpenCAX {
* Copyright (c) 2024 Huawei Device Co., Ltd. setFrameRate(nodeId: string, min: number, max: number, expected: number): void;
* Licensed under the Apache License, Version 2.0 (the "License"); setNeedSoftKeyboard(nodeId: string, need: boolean): void;
* you may not use this file except in compliance with the License. }
* You may obtain a copy of the License at export function createNativeNode(nodeContent: any, nodeId: string): void;
* export function loadModel(stepFilePath: string): void;
* 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.
*/
import { NodeContent } from '@ohos.arkui.node';
type XComponentContextStatus = {
hasDraw: boolean,
hasChangeColor: boolean
};
export const createNativeNode: (content: NodeContent, tag: string) => void;
export const drawPattern: () => void;
export const setFrameRate: (id: string, min: number, max: number, expected: number) => void;
export const setNeedSoftKeyboard: (id: string, needSoftKeyborad: boolean) => void;

View File

@ -66,8 +66,7 @@ export struct ModelView {
Button('加载模型').onClick(()=>{ Button('加载模型').onClick(()=>{
try { try {
console.info('Model copied to:', this.modelPath); console.info('Model copied to:', this.modelPath);
NativeOpenCAX.drawPattern(); NativeOpenCAX.loadModel(this.modelPath);
//NativeOpenCAX.loadModel(this.displayContrId,this.modelPath);
} catch (e) { } catch (e) {
hilog.error(0x0000, 'ModelView', `LoadModel Failed: ${JSON.stringify(e)}`); hilog.error(0x0000, 'ModelView', `LoadModel Failed: ${JSON.stringify(e)}`);
} }