背景介绍
支持将外部自渲染内容(无论是通过 NativeDrawing 等OHOS CAPI 绘制,还是通过 OpenGL 相关接口绘制)通过外接纹理的方式导入 Flutter 的 Texture 组件进行展示。以下是具体实现方法。
使用前提
Flutter版本需要3.22及以上
实现步骤
1. Dart 侧操作
1.1 创建Texture组件
- 创建Texture组件,绑定textureId
1.2 注册纹理
-
创建
MethodChannel:final MethodChannel _channel = const MethodChannel('PictureChannel1');
-
在
initState函数中注册纹理:_textureId = await _channel.invokeMethod("registerStarTexture");
1.3 注销纹理
-
在
dispose函数中注销纹理:_channel.invokeMethod('unregisterTexture', {'textureId': _textureId});
2. OHOS侧操作
2.1 引入工具类
需要引入以下工具类:
import { TextureRegistry, SurfaceTextureEntry } from '@ohos/flutter_ohos/src/main/ets/view/TextureRegistry';
2.2 提供的实现方式
提供了两种将自渲染内容导入 Flutter 纹理的实现方式。
实现方式一:通过 getNativeWindowId 绘制到 Buffer
通过 getNativeWindowId 获取引擎层 Texture 对应的 OHNativeWindow 指针,然后将自渲染内容绘制到该 window 对应的 Buffer 上。
ArkTS 侧实现步骤
- 注册纹理时获取相关信息:
this.textureId = this.textureRegistry!.getTextureId();
this.surfaceTextureEntry = this.textureRegistry!.registerTexture(this.textureId);
this.windowId = this.surfaceTextureEntry.getNativeWindowId();
drawNapi.drawPatternWindow(this.windowId, 300, 300);// 需要在cpp层实现draw函数,接收window指针
-
调用
cpp层函数,将自渲染内容绘制到该window:drawNapi.drawPatternWindow(this.windowId, 300, 300); // 需要在 cpp 层实现此函数
CPP 侧实现步骤
- 使用
OH_NativeWindow_NativeWindowHandleOpt设置window的USAGE、宽高等信息。 - 调用
OH_NativeWindow_NativeWindowRequestBuffer获取window的 Buffer。 - 使用
OH_NativeWindow_GetBufferHandleFromNative获取bufferHandle。 - 使用
OH_NativeWindow_NativeWindowFlushBuffer将生产好的 Buffer 放到 Buffer 队列中供消费。
实现方式二:通过 setExternalNativeImage
直接将用于内容生产的 NativeImage 指针传递给 Flutter 引擎层,由引擎层利用该 NativeImage 通过 OH_NativeImage_SetOnFrameAvailableListener 注册帧可用回调进行内容消费。
ArkTS 侧实现步骤
- 注册纹理时获取相关信息:
this.textureId = this.textureRegistry!.getTextureId();
this.surfaceTextureEntry = this.textureRegistry!.registerTexture(this.textureId);
drawNapi.drawPatternWindow(1000, 1000);
this.nativeImageId = drawNapi.getNativeImage();// 获取用于内容生产的NativeImage
this.textureRegistry!.setExternalNativeImage(this.textureId, this.nativeImageId);// 将NativeImage传入引擎层
CPP 侧实现步骤
以下为基于 OpenGL 的简单绘制实现步骤:
- 使用
OH_NativeImage_Create创建NativeImage。 - 使用
OH_NativeImage_AcquireNativeWindow获取NativeImage关联的window。 - 使用
OH_NativeWindow_NativeWindowHandleOpt设置USAGE和宽高。 - 将
NativeWindow转换为EGLNativeWindowType类型。 - 调用以下 OpenGL 相关指令完成绘制:
eglCreateWindowSurfaceeglCreateContexteglMakeCurrentgl绘制相关指令eglSwapBuffers
纹理注销
无论使用上述哪种方式,都需要调用以下函数进行纹理注销:
this.textureRegistry!.unregisterTexture(textureId);
参考实现
实现参考
代码位置说明
-
Dart 侧代码
方式一: 相关代码位于lib/PicturePage1.dart,最下方添加的纹理组件用于自渲染内容导入。
方式二: 相关代码位于lib/PicturePage2.dart。 -
ArkTS 侧代码
方式一: 相关代码位于ohos/entry/src/main/ets/entryability/PicturePlugin1.ets,包含了纹理的注册和注销函数。
方式二: 相关代码位于ohos/entry/src/main/ets/entryability/PicturePlugin2.ets。 -
原生绘制代码
相关代码位于ohos/entry/src/main/cpp。
注意事项
- 开发者在使用方式二时,需要自行管理
NativeImage的生命周期,并确保在unregister前对象不会销毁。