未验证 提交 b568682d 编写于 作者: O openharmony_ci 提交者: Gitee

!10903 更新NativeWindow NAPI 使用指导

Merge pull request !10903 from Andrew0229/cherry-pick-1666316104
...@@ -2,112 +2,105 @@ ...@@ -2,112 +2,105 @@
## 场景介绍 ## 场景介绍
NativeWindow是`OpenHarmony`**本地平台化窗口**包括从`Surface`构建`NativeWindow`,从`SurfaceBuffer`构建出`NativeWindowBuffer`的能力,开发者可以通过`NativeWindow`接口进行申请和提交`Buffer` NativeWindow是`OpenHarmony`**本地平台化窗口**表示图形队列的生产者端。接口能力包括从`Surface`构建`NativeWindow`的能力,从`SurfaceBuffer`构建出`NativeWindowBuffer`的能力,开发者可以通过`NativeWindow`接口进行申请和提交`Buffer`
针对NativeWindow,常见的开发场景如下: 针对NativeWindow,常见的开发场景如下:
* 通过`Native C++`代码绘制内容并显示在屏幕上 * 通过`NativeWindow`提供的`NAPI`接口申请图形`Buffer`,并将生产图形内容写入图形`Buffer`,最终提交`Buffer`到图形队列
* 在适配EGL层的`eglswapbuffer`接口时,进行提交和申请`Buffer` * 在适配EGL层的`eglswapbuffer`接口时,进行申请和提交`Buffer`
## 接口说明 ## 接口说明
| 接口名 | 描述 | | 接口名 | 描述 |
| -------- | -------- | | -------- | -------- |
| OH_NativeWindow_CreateNativeWindowFromSurface (void \*pSurface) | 创建NativeWindow实例,每次调用都会产生一个新的NativeWindow实例。 | | OH_NativeWindow_CreateNativeWindowFromSurface (void \*pSurface) | 创建NativeWindow实例,每次调用都会产生一个新的NativeWindow实例。 |
| OH_NativeWindow_DestroyNativeWindow (struct NativeWindow \*window) | 将NativeWindow对象的引用计数减1,当引用计数为0的时候,该NativeWindow对象会被析构掉。 | | OH_NativeWindow_DestroyNativeWindow (OHNativeWindow \*window) | 将NativeWindow对象的引用计数减1,当引用计数为0的时候,该NativeWindow对象会被析构掉。 |
| OH_NativeWindow_CreateNativeWindowBufferFromSurfaceBuffer (void \*pSurfaceBuffer) | 创建NativeWindowBuffer实例,每次调用都会产生一个新的NativeWindowBuffer实例。 | | OH_NativeWindow_CreateNativeWindowBufferFromSurfaceBuffer (void \*pSurfaceBuffer) | 创建NativeWindowBuffer实例,每次调用都会产生一个新的NativeWindowBuffer实例。 |
| OH_NativeWindow_DestroyNativeWindowBuffer (struct NativeWindowBuffer \*buffer) | 将NativeWindowBuffer对象的引用计数减1,当引用计数为0的时候,该NativeWindowBuffer对象会被析构掉。 | | OH_NativeWindow_DestroyNativeWindowBuffer (OHNativeWindowBuffer \*buffer) | 将NativeWindowBuffer对象的引用计数减1,当引用计数为0的时候,该NativeWindowBuffer对象会被析构掉。 |
| OH_NativeWindow_NativeWindowRequestBuffer (struct NativeWindow \*window struct NativeWindowBuffer \*\*buffer, int \*fenceFd) | 通过NativeWindow对象申请一块NativeWindowBuffer,用以内容生产。 | | OH_NativeWindow_NativeWindowRequestBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*\*buffer, int \*fenceFd) | 通过NativeWindow对象申请一块NativeWindowBuffer,用以内容生产。 |
| OH_NativeWindow_NativeWindowFlushBuffer (struct NativeWindow \*window, struct NativeWindowBuffer \*buffer, int fenceFd, Region region) | 通过NativeWindow将生产好内容的NativeWindowBuffer放回到Buffer队列中,用以内容消费。 | | OH_NativeWindow_NativeWindowFlushBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*buffer, int fenceFd, Region region) | 通过NativeWindow将生产好内容的NativeWindowBuffer放回到Buffer队列中,用以内容消费。 |
| OH_NativeWindow_NativeWindowCancelBuffer (struct NativeWindow \*window, struct NativeWindowBuffer \*buffer) | 通过NativeWindow将之前申请出来的NativeWindowBuffer返还到Buffer队列中,供下次再申请。 | | OH_NativeWindow_NativeWindowAbortBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*buffer) | 通过NativeWindow将之前申请出来的NativeWindowBuffer返还到Buffer队列中,供下次再申请。 |
| OH_NativeWindow_NativeWindowHandleOpt (struct NativeWindow \*window, int code,...) | 设置/获取NativeWindow的属性,包括设置/获取宽高、内容格式等。 | | OH_NativeWindow_NativeWindowHandleOpt (OHNativeWindow \*window, int code,...) | 设置/获取NativeWindow的属性,包括设置/获取宽高、内容格式等。 |
| OH_NativeWindow_GetBufferHandleFromNative (struct NativeWindowBuffer \*buffer) | 通过NativeWindowBuffer获取该buffer的BufferHandle指针。 | | OH_NativeWindow_GetBufferHandleFromNative (OHNativeWindowBuffer \*buffer) | 通过NativeWindowBuffer获取该buffer的BufferHandle指针。 |
| OH_NativeWindow_NativeObjectReference (void \*obj) | 增加一个NativeObject的引用计数。 | | OH_NativeWindow_NativeObjectReference (void \*obj) | 增加一个NativeObject的引用计数。 |
| OH_NativeWindow_NativeObjectUnreference (void \*obj) | 减少一个NativeObject的引用计数,当引用计数减少为0时,该NativeObject将被析构掉。 | | OH_NativeWindow_NativeObjectUnreference (void \*obj) | 减少一个NativeObject的引用计数,当引用计数减少为0时,该NativeObject将被析构掉。 |
| OH_NativeWindow_GetNativeObjectMagic (void \*obj) | 获取NativeObject的MagicId。 | | OH_NativeWindow_GetNativeObjectMagic (void \*obj) | 获取NativeObject的MagicId。 |
| OH_NativeWindow_NativeWindowSetScalingMode (OHNativeWindow \*window, uint32_t sequence, OHScalingMode scalingMode) | 设置NativeWindow的缩放模式。 |
| OH_NativeWindow_NativeWindowSetMetaData(OHNativeWindow \*window, uint32_t sequence, int32_t size, const OHHDRMetaData \*metaData) | 设置NativeWindow的HDR静态元数据。 |
| OH_NativeWindow_NativeWindowSetMetaDataSet(OHNativeWindow \*window, uint32_t sequence, OHHDRMetadataKey key, int32_t size, const uint8_t \*metaData) | 设置NativeWindow的HDR静态元数据集。 |
| OH_NativeWindow_NativeWindowSetTunnelHandle(OHNativeWindow \*window, const OHExtDataHandle \*handle) | 设置NativeWindow的TunnelHandle。 |
详细的接口说明请参考[native_window](../reference/native-apis/_native_window.md) 详细的接口说明请参考[native_window](../reference/native-apis/_native_window.md)
## 开发步骤 ## 开发步骤
以下步骤描述了在**OpenHarmony**中如何利用`OH_NativeXComponent`通过`Native C++`代码绘制内容并显示在屏幕上 以下步骤描述了在**OpenHarmony**中如何使用`NativeWindow`提供的`NAPI`接口,申请图形`Buffer`,并将生产图形内容写入图形`Buffer`后,最终提交`Buffer`到图形队列
1. **在页面中定义XComponent组件**,在`index.ets`中定义一个`texture`类型的`XComponent`,用于显示内容。 1. **获取NativeWindow实例**。例如,使用`Surface`创建`NativeWindow`实例。
```js ```c++
XComponent({ id: 'xcomponentId', type: 'texture', libraryname: 'nativerender'}) sptr<OHOS::Surface> cSurface = Surface::CreateSurfaceAsConsumer();
.borderColor(Color.Red) sptr<IBufferConsumerListener> listener = new BufferConsumerListenerTest();
.borderWidth(5) cSurface->RegisterConsumerListener(listener);
.onLoad(() => {}) sptr<OHOS::IBufferProducer> producer = cSurface->GetProducer();
.onDestroy(() => {}) sptr<OHOS::Surface> pSurface = Surface::CreateSurfaceAsProducer(producer);
``` OHNativeWindow* nativeWindow = OH_NativeWindow_CreateNativeWindow(&pSurface);
```
2. **获取OH_NativeXComponent实例**。使用 `napi_get_named_property` 接口获取一个`OH_NativeXComponent`实例 `nativeXComponent`,通过注册该实例的回调接口获取`NativeWindow`实例。
2. **设置NativeWindowBuffer的属性**。使用`OH_NativeWindow_NativeWindowHandleOpt`设置`NativeWindowBuffer`的属性。
```c++ ```c++
// 定义 napi instance // 设置 NativeWindowBuffer 的读写场景
napi_value exportInstance = nullptr; int code = SET_USAGE;
// 定义一个 OH_NativeXComponent 实例 int32_t usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
OH_NativeXComponent *nativeXComponent = nullptr; int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, usage);
// 通过 OH_NATIVE_XCOMPONENT_OBJ export 实例 // 设置 NativeWindowBuffer 的宽高
napi_getname_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance); code = SET_BUFFER_GEOMETRY;
// 将 napi instance 转化为 OH_NativeXComponent 实例 int32_t width = 0x100;
napi_unwarp(env, exportInstance, reinterpret_cast<void**>(&nativeXComponent)); int32_t height = 0x100;
ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height);
// 设置 NativeWindowBuffer 的步长
code = SET_STRIDE;
int32_t stride = 0x8;
ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, stride);
// 设置 NativeWindowBuffer 的格式
code = SET_FORMAT;
int32_t format = PIXEL_FMT_RGBA_8888;
ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, format);
``` ```
3. **定义回调函数OnSurfaceCreated**。用于在`Surface`创建时,通过回调函数初始化开发者的渲染环境,例如`Skia`渲染环境。并将要显示的内容写入`NativeWindow` 3. **从图形队列申请NativeWindowBuffer**
```c++
struct NativeWindowBuffer* buffer = nullptr;
int fenceFd;
// 通过 OH_NativeWindow_NativeWindowRequestBuffer 获取 NativeWindowBuffer 实例
OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow_, &buffer, &fenceFd);
// 通过 OH_NativeWindow_GetNativeBufferHandleFromNative 获取 buffer 的 handle
BufferHandle* bufferHandle = OH_NativeWindow_GetNativeBufferHandleFromNative(buffer);
```
4. **将生产的内容写入NativeWindowBuffer**
```c++ ```c++
void OnSurfaceCreatedCB(NativeXComponent* component, void* window) { auto image = static_cast<uint8_t *>(buffer->sfbuffer->GetVirAddr());
//获取 native window 的宽高 static uint32_t value = 0x00;
uint64_t width_ = 0, height_ = 0; value++;
OH_NativeXComponent_GetXComponentSize(nativeXComponent, window, &width_, &height_);
// 将void* 转换为 NativeWindow 实例,NativeWindow 定义在 native_window/external_window.h 中 uint32_t *pixel = static_cast<uint32_t *>(image);
NativeWindow* nativeWindow_ = (NativeWindow*)(window); for (uint32_t x = 0; x < width; x++) {
for (uint32_t y = 0; y < height; y++) {
// 通过 OH_NativeWindow_NativeWindowHandleOpt 设置或者获取NativeWindow的属性 *pixel++ = value;
// 1.通过 SET_USAGE 设置 Native Window 的 usage 属性, 例如:HBM_USE_CPU_READ }
OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, HBM_USE_CPU_READ | HBM_USE_CPU_WRITE |HBM_USE_MEM_DMA);
// 2.通过 SET_BUFFER_GEOMETRY 设置 Native Window 的 宽高属性
OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_BUFFER_GEOMETRY, width_, height_);
// 3.通过 SET_FORMAT 设置 Native Window 的 format 属性, 例如:PIXEL_FMT_RGBA_8888
OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_FORMAT, PIXEL_FMT_RGBA_8888);
// 4.通过 SET_STRIDE 设置 Native Window 的 stride 属性
OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_STRIDE, 0x8);
// 通过 OH_NativeWindow_NativeWindowRequestBuffer 获取 NativeWindowBuffer 实例
struct NativeWindowBuffer* buffer = nullptr;
int fenceFd;
OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow_, &buffer, &fenceFd);
// 通过 OH_NativeWindow_GetNativeBufferHandleFromNative 获取 buffer handle
BufferHandle* bufferHandle = OH_NativeWindow_GetNativeBufferHandleFromNative(buffer);
// 通过 BufferHandle 创建Skia Bitmap
SkBitmap bitmap;
SkImageInfo imageInfo = ...
bitmap.setInfo(imageInfo, bufferHandle->stride);
bitmap.setPixels(bufferHandle->virAddr);
//创建 Skia Canvas 并将内容写入native window
...
//写入完成后,通过OH_NativeWindow_NativeWindowFlushBuffer 提交给消费者使用,例如:显示在屏幕上
Region region{nullptr, 0};
OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow_, buffer, fenceFd, region)
} }
``` ```
4. **注册回调函数OnSurfaceCreated等**。使用 `OH_NativeXComponent_RegisterCallback` 接口注册上一步中创建的回调函数 5. **提交NativeWindowBuffer到图形队列**
```c++ ```c++
OH_NativeXComponent_Callback &callback_; // 设置刷新区域,如果Region中的Rect为nullptr,或者rectNumber为0,则认为NativeWindowBuffer全部有内容更改。
callback_->OnSurfaceCreated = OnSurfaceCreatedCB; Region region{nullptr, 0};
callback_->OnSurfaceChanged = OnSurfaceChangedCB; // 通过OH_NativeWindow_NativeWindowFlushBuffer 提交给消费者使用,例如:显示在屏幕上。
callback_->OnSurfaceDestroyed = OnSurfaceDestroyedCB; OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow_, buffer, fenceFd, region);
callback_->DispatchTouchEvent = DispatchTouchEventCB;
OH_NativeXComponent_RegisterCallback(nativeXComponent, callback_)
``` ```
## 相关实例 ## 相关实例
针对NativeWindow的使用,有以下相关实例可供参考: 针对NativeWindow的使用,有以下相关实例可供参考:
- [使用NativeWindow接口获取Buffer](https://gitee.com/openharmony/graphic_graphic_2d/blob/master/rosen/samples/hello_native_window/hello_native_window.cpp) - [使用NativeWindow接口获取并提交Buffer](https://gitee.com/openharmony/graphic_graphic_2d/blob/master/rosen/samples/hello_native_window/hello_native_window.cpp)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册