HarmonyOS 鸿蒙Next自定义渲染(XComponent)入门介绍

HarmonyOS 鸿蒙Next自定义渲染(XComponent)入门介绍

1. 背景说明

HarmonyOS平台视频开发过程中,难免有自定义视频处理的需求,如直播美颜等等。本文章是关于自定义渲染 (XComponent)的流程梳理。

图片

2. EGL(画布)

EGL是Embedded Graphics Library的缩写,可以翻译为嵌入式图形接口库,主要作用是连接 OpenGL/OpenGL ES 渲染 API 与操作系统原生窗口系统 的核心中间层。

EGL初始化主要包括三个步骤:

1) 获取EGLDisplay,用于连接本地窗口系统。

m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);

2) 初始化EGL,主要检查 m_eglDisplay是否有效,并加载 EGL 库(如 libEGL.so)及其依赖的图形驱动。

EGLint majorVersion;
EGLint minorVersion;
int i_err = eglInitialize(m_eglDisplay, &majorVersion, &minorVersion)

3) 选择设备适合的EGLConfig

const EGLint ATTRIB_LIST[] = {
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,  // 支持窗口渲染
    EGL_RED_SIZE, 8,                   // 红色通道8位
    EGL_GREEN_SIZE, 8,                 // 绿色通道8位
    EGL_BLUE_SIZE, 8,                  // 蓝色通道8位
    EGL_ALPHA_SIZE, 8,                 // Alpha通道8位(可选)
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // 支持 OpenGL ES 2.0
    EGL_NONE                           // 结束标记
};

// 选择EGLConfig.
const EGLint maxConfigSize = 1;//只选择符合条件中优先级最高的一个配置
EGLint numConfigs;//符合条件的配置数,若没有匹配的,返回0。
if (!eglChooseConfig(m_eglDisplay, ATTRIB_LIST, &m_eglConfig, maxConfigSize, &numConfigs))
{
    //错误处理
}

4) 创建EGL上下文

const EGLint CONTEXT_ATTRIBS[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};//指定 OpenGL ES 版本为 2.0
m_eglContext = eglCreateContext(m_eglDisplay, 
                                m_eglConfig, 
                                EGL_NO_CONTEXT, //不共享上下文
                                CONTEXT_ATTRIBS);

5) 创建EGL 离屏渲染表面,主要用于在HarmonyOS(HarmonyOS)平台上创建一个离屏的 EGLSurface,用于 ​后台渲染​(如滤镜处理、图像合成等不直接显示到屏幕的场景)。

const EGLint surfaceAttribs[] = {
    EGL_WIDTH, width,
    EGL_HEIGHT, height,
    EGL_NONE};   

m_eglOffScreenSurface = eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, surfaceAttribs);

6) 绑定OpenGL所在的线程(eglMakeCurrent), 将渲染上下文(EGLContext)、渲染表面(EGLSurface)与当前线程关联,从而建立完整的 OpenGL ES 渲染环境。

eglMakeCurrent(m_eglDisplay, m_eglOffScreenSurface, m_eglOffScreenSurface, m_eglContext)

7) 创建定时器,1000/FPS 秒绘制一次 //实际上为native侧实现,这里使用ts便于理解 setInterval(() => { //添加OpenGL线程绘制任务 }, 1000/mFps);

3. OpenGL (画笔)

OpenGL的全称是 ​Open Graphics Library​(开放式图形库),它是一种跨语言、跨平台的应用程序编程接口(API),专门用于渲染2D和3D矢量图形。

1) 生成纹理ID

glGenTextures(1, &m_texture);

2) 设置textureTarget纹理目标

// 定义纹理目标类型为GL_TEXTURE_EXTERNAL_OES(用于外部图像流,如相机/视频)
uint32_t target = GL_TEXTURE_EXTERNAL_OES;

// 设置纹理缩小过滤方式为线性过滤(当纹理被缩小时使用)
// GL_LINEAR会基于周围纹素插值计算颜色,使缩小后的纹理更平滑
glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  

// 设置纹理放大过滤方式为线性过滤(当纹理被放大时使用)
// GL_LINEAR通过加权平均周围4个纹素,减少放大时的锯齿感
glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  

// 设置纹理S轴(水平方向)的环绕方式为边缘截取
// GL_CLAMP_TO_EDGE表示超出[0,1]范围的坐标会使用边缘像素填充
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  

// 设置纹理T轴(垂直方向)的环绕方式为边缘截取
// 避免纹理在边缘处重复或镜像,适用于需要严格对齐的场景(如视频帧)
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

3) 创建​nativeImage​,并将纹理目标绑定到纹理ID

//HarmonyOS提供的接口内部已经实现绑定操作
m_nativeImage = OH_NativeImage_Create(m_texture, target);

//若为Android等平台需要显示的绑定纹理目标到纹理ID
glBindTexture(target, m_texture)

4) 设置帧可用回调

OH_OnFrameAvailableListener listener;
listener.context = this;
listener.onFrameAvailable = pri_OH_OnFrameAvailable;
OH_NativeImage_SetOnFrameAvailableListener(m_nativeImage, listener);
//有可用帧,可以开始draw到surface了。
void static pri_OH_OnFrameAvailable(void *context)
{
    OGRenderWindowBridge*the = (OGRenderWindowBridge*)context;
    the->m_bRead = true;
}

5) 创建nativeWindow,并获取对应的surfaceId,用于接收相机传输的数据

m_nativeWindow = OH_NativeImage_AcquireNativeWindow(m_nativeImage);
OH_NativeImage_GetSurfaceId(m_nativeImage, &o_surfaceId);

4. 启用XComponent

1) 创建自定义XComponentController

//新建XComponentController
class MyXComponentController extends XComponentController{
  public myXComponentInfo: MyXComponentInfo;

  public constructor(myXComponentInfo: MyXComponentInfo) {
    super();
    this.myXComponentInfo = myXComponentInfo;
  }

  onSurfaceCreated(surfaceId: string): void {
      //native侧初始化,包括EGL,OpenGL,以及myXComponentInfo参数传递到native侧

      //将该XComponent对应的surfaceId通过napi传递给native侧,创建对应的nativeWindow作为XComponent的生产者。
      setWindow(surfaceId, rect.surfaceWidth, rect.surfaceHeight, 1)

      //将OpenGL对应的surfaceId绑定给相机,相机作为生产者
  }

  onSurfaceChanged(surfaceId: string, rect: SurfaceRect): void {
      //通过napi调用native侧代码,重新setWindow
      setWindow(surfaceId, rect.surfaceWidth, rect.surfaceHeight, 1)
  }

  onSurfaceDestroyed(surfaceId: string): void {

  }
}

2) 创建XComponent

build() {
  XComponent({
    id: 'MyXComponent',
    type: XComponentType.SURFACE,
    controller: this.myXComponentController
  })
    .position({ x: this.myXComponentInfo.x, y: this.myXComponentInfo.y })
    .width(this.myXComponentInfo.w)
    .height(this.myXComponentInfo.h)
}

3) native侧核心设置代码,ts侧需要通过napi调用。

int setWindow(int64_t surfaceId, int i_width, int i_height, int i_state)
{
    //native侧处理XComponent对应的surfaceId
    OHNativeWindow* XComponentWindow;
    OH_NativeWindow_CreateNativeWindowFromSurfaceId(surfaceId, &XComponentWindow);
    eglSurface = eglCreateWindowSurface(XComponentWindow, m_eglConfig, m_eglWindow, NULL);
    //这里宽高代表分辨率,如i_width = 720,i_height = 1280 代表需要绘制的分辨率为720p。
    //添加到渲染队列中
    m_eglSurfaceQueue.push_back(eglSurface, i_width, i_height, i_state);
}

5. 相关参考文档


更多关于HarmonyOS 鸿蒙Next自定义渲染(XComponent)入门介绍的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

大佬,学到了!

更多关于HarmonyOS 鸿蒙Next自定义渲染(XComponent)入门介绍的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


HarmonyOS Next的XComponent提供自定义渲染能力,支持OpenGL ES、OpenCL等图形接口。通过XComponent组件,开发者可在鸿蒙应用内创建独立的渲染区域,实现高性能图形绘制、视频处理或游戏渲染。其核心接口包括XComponentController,用于管理渲染生命周期与回调。开发时需在module.json5中声明XComponent能力,并在ArkTS/ArkUI中配置组件属性与事件。

HarmonyOS Next自定义渲染(XComponent)入门介绍

这篇关于HarmonyOS Next自定义渲染(XComponent)的入门介绍非常全面,清晰地梳理了从EGL初始化、OpenGL纹理处理到XComponent集成的核心流程。对于需要进行视频美颜、滤镜等自定义渲染的开发者来说,这是一个很好的起点。

文章结构合理,将复杂的图形渲染管线分解为“画布”(EGL)和“画笔”(OpenGL)两个部分,最后与ArkUI的XComponent组件对接,逻辑清晰。其中,对OH_NativeImageOH_NativeWindow等HarmonyOS特有接口的运用是关键,它们替代了传统Android平台上SurfaceTexture等组件的功能,是连接系统图形层与自定义OpenGL ES渲染的核心桥梁。

几个值得强调的技术要点:

  1. 线程绑定eglMakeCurrent的调用至关重要,它确立了OpenGL ES命令的执行线程环境。
  2. 纹理目标:使用GL_TEXTURE_EXTERNAL_OES处理来自相机或视频解码器的外部图像流,这是实现高效视频纹理渲染的标准做法。
  3. 双Surface架构:文中示例同时使用了离屏的EGL Pbuffer Surface(用于后台处理)和由XComponent提供的窗口EGL Window Surface(用于最终显示),这种设计为复杂的图像处理(如多级滤镜)提供了灵活性。
  4. 生命周期管理:在XComponentController的回调(onSurfaceCreated, onSurfaceChanged, onSurfaceDestroyed)中正确地初始化和释放Native资源,是保证应用稳定性和避免内存泄漏的关键。

提供的参考文档链接都是官方的核心指南,建议开发者深入阅读,特别是NativeImage和NativeWindow的开发指导,它们详细说明了HarmonyOS图形子系统的工作机制。

总的来说,这是一份高质量的技术流程总结,遵循此流程可以成功在HarmonyOS Next上搭建起自定义图形渲染的基础框架。后续开发者可以在此基础上,专注于实现具体的OpenGL ES着色器程序,来完成美颜、风格化等具体的图像处理效果。

回到顶部