XComponent使用OpenGl ES

XComponent使用OpenGl ES


HarmonyOS
2024-06-11 20:47:27
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
开心的兔子

此场景开发可参考:

https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-camera.md

https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/video-recorder.md

https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/arkui-ts/ts-basic-components-xcomponent.md

Demo 参考:

相机预览:https://gitee.com/openharmony/app_samples/tree/master/media/MultiMedia

播放器:https://gitee.com/openharmony/app_samples/tree/master/media/VideoPlayer

提供C++层使用OpenGL做渲染的开发方式

XComponent组件通过提供NDK接口为开发者在C++层提供NativeWindow用来创建EGL/GLES环境,进而开发者可以使用标准OpenGL ES 开发渲染逻辑XComponent 官方NDK Demo请参考:https://gitee.com/openharmony/app_samples/tree/master/ETSUI/XComponent

XComponent的开发需要使用NDK,相关NDK头文件可参考:https://gitee.com/openharmony/arkui_ace_engine/blob/master/interfaces/native/native_interface_xcomponent.h

开发流程&原理解析

这里主要介绍基于XComponent的C++层OpenGL渲染的开发场景。

XComponent 主要为开发者提供:

TS/JS层:符合ArkUI 开发规范的UI组件

C++层:

组件TS描述

开发者在TS/JS层用如下代码即可使用XComponent组件

1XComponent({ id: 'xcomponentId', type: 'texture', libraryname: 'nativerender'})2  .onLoad((context) => {3    this.context = context;4  })5  .onDestroy(() => {6  })

XComponent组件构建时参数含义:

  • 直接使用NAPI机制,使用import方式加载
1import nativerender from "libnativerender.so";

这种方式可以实现JS层通过nativerender实例跨语言调用libnativerender.so中的native方法。

  • 使用xcomponent组件加载

XComponent组件通过指定libraryname来加载动态库,本质上也是通过NAPI机制加载动态库的。与import方式的区别在于,加载动态库时会将XComponent的NativeXComponent实例暴露到应用的C++层,让开发者在C++层可使用XComponent开发渲染逻辑。

XComponent组件事件含义:

onDestroy

XComponent组件被销毁时触发,XComponent组件销毁的逻辑符合ArkUI 的UI组件生命周期。

Native层开发

C++代码开发关键点

NAPI机制对接

关键代码如下

1static napi_module nativerenderModule = {2    .nm_version = 1,3    .nm_flags = 0,4    .nm_filename = nullptr,5    .nm_register_func = Init,    // 指定加载的so时的回调入口6    .nm_modname = "nativerender",  // 指定可被NAPI机制加载的so名称,XComponent的libraryname与该名称保持一直,否则无法加载so7    .nm_priv = ((void*)0),8    .reserved = { 0 },9};10/*11 * Module register function12 */13extern "C" __attribute__((constructor)) void RegisterModule(void)14{15    napi_module_register(&nativerenderModule);16}

NAPI入口函数

由上文可知,通过nm_register_func指定so加载时的注册函数,如下面函数init

1static napi_value Init(napi_env env, napi_value exports)2{3    LOGE("Init");4    napi_property_descriptor desc[] ={5        DECLARE_NAPI_FUNCTION("getContext", PluginManager::GetContext),6    };7    NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));8 9    bool ret = PluginManager::GetInstance()->Export(env, exports);10    if (!ret) {11        LOGE("Init failed");12    }13    return exports;14}

该nm_register_func函数的调用时刻是so被import时或者被XComponent用libraryname加载时。

在该函数被调用中,开发者可对参数exports上挂载C方法

如官方Demo中在JS层跨语言调用的changeColor,changeShape等方法。

1napi_value PluginRender::Export(napi_env env, napi_value exports)2{3    LOGE("PluginRender::Export");4    // Register JS API5    napi_property_descriptor desc[] = {6        DECLARE_NAPI_FUNCTION("changeShape", PluginRender::NapiChangeShape),7        DECLARE_NAPI_FUNCTION("drawTriangle", PluginRender::NapiDrawTriangle),8        DECLARE_NAPI_FUNCTION("changeColor", PluginRender::NapiChangeColor),9    };10    NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));11    return exports;12}

exports会通过JS 引擎绑定到JS层的一个JS对象,该JS对象是指中的

nativerender,也指XComponent onLoad事件的Context

1import nativerender from "libnativerender.so";

解析XComponent UI组件的NativeXComponent实例

当so被XComponent加载时,会将NativeXComponent实例的指针绑定到nm_register_func注册函数的第二个入参上(即上文中Init(napi_env env, napi_value exports)函数的入参exports,下文都以exports为例)。

解析XComponent的NativeXComponent实例关键代码段如下:

1status = napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);2if (status != napi_ok) {3    return false;4}5 6status = napi_unwrap(env, exportInstance, reinterpret_cast<void**>(&nativeXComponent));7if (status != napi_ok) {8    return false;9}

其中使用OH_NATIVE_XCOMPONENT_OBJ来解析wrap了NativeXComponent指针的属性,然后通过napi_unwrap接口解析出NativeXComponent实例指针

XComponent NDK使用

XComponent NDK接口的使用都依赖于XComponent的NativeXComponent实例指针

开发者拿到NativeXComponent实例指针后要通过OH_NativeXComponent_RegisterCallback方法进行回调注册。这个过程必须在nm_register_func注册的函数中同步完成。

XComponent NDK接口的使用主要包括:

Touch事件:

1. XComponent为开发者提供Touch事件回调接口,支持多指事件。

线程模型

XComponent作为UI组件,所在线程为应用的主线程。XComponent的NDK接口回调都在主线程中,开发者可在拿到Nativewindow句柄后,在自己的线程中创建EGL/OpenGLES 环境。所有线程的处理依赖开发者自己实现。

分享
微博
QQ
微信
回复
2024-06-12 22:28:23
相关问题
HarmonyOS OPENGL ES外部纹理使用
313浏览 • 1回复 待解决
XComponentopenGL实现3D图形绘制
1685浏览 • 1回复 待解决
HarmonyOS VideoDecoder使用OpenGL渲染
170浏览 • 1回复 待解决
如何用openGL做解码后处理
1725浏览 • 0回复 待解决
OpenGL相关术语的理解
336浏览 • 1回复 待解决
HarmonyOS AVPlayer XComponent
361浏览 • 1回复 待解决
使用Native、XComponent和EGL绘制图形
987浏览 • 1回复 待解决
OpenSL ES音频录制示例调用崩溃
1929浏览 • 1回复 待解决
Xcomponent绘图流程分析
1420浏览 • 1回复 待解决
OpenGL无法正常渲染某些分辨率YUV数据
420浏览 • 0回复 待解决