1# NativeWindow 开发指导 2 3## 场景介绍 4 5NativeWindow是`OpenHarmony`**本地平台化窗口**,包括从`Surface`构建`NativeWindow`,从`SurfaceBuffer`构建出`NativeWindowBuffer`的能力,开发者可以通过`NativeWindow`接口进行申请和提交`Buffer`。 6针对NativeWindow,常见的开发场景如下: 7 8* 通过`Native C++`代码绘制内容并显示在屏幕上 9* 在适配EGL层的`eglswapbuffer`接口时,进行提交和申请`Buffer` 10 11## 接口说明 12 13| 接口名 | 描述 | 14| -------- | -------- | 15| OH_NativeWindow_CreateNativeWindowFromSurface (void \*pSurface) | 创建NativeWindow实例,每次调用都会产生一个新的NativeWindow实例。 | 16| OH_NativeWindow_DestroyNativeWindow (struct NativeWindow \*window) | 将NativeWindow对象的引用计数减1,当引用计数为0的时候,该NativeWindow对象会被析构掉。 | 17| OH_NativeWindow_CreateNativeWindowBufferFromSurfaceBuffer (void \*pSurfaceBuffer) | 创建NativeWindowBuffer实例,每次调用都会产生一个新的NativeWindowBuffer实例。 | 18| OH_NativeWindow_DestroyNativeWindowBuffer (struct NativeWindowBuffer \*buffer) | 将NativeWindowBuffer对象的引用计数减1,当引用计数为0的时候,该NativeWindowBuffer对象会被析构掉。 | 19| OH_NativeWindow_NativeWindowRequestBuffer (struct NativeWindow \*window, struct NativeWindowBuffer \*\*buffer, int \*fenceFd) | 通过NativeWindow对象申请一块NativeWindowBuffer,用以内容生产。 | 20| OH_NativeWindow_NativeWindowFlushBuffer (struct NativeWindow \*window, struct NativeWindowBuffer \*buffer, int fenceFd, Region region) | 通过NativeWindow将生产好内容的NativeWindowBuffer放回到Buffer队列中,用以内容消费。 | 21| OH_NativeWindow_NativeWindowCancelBuffer (struct NativeWindow \*window, struct NativeWindowBuffer \*buffer) | 通过NativeWindow将之前申请出来的NativeWindowBuffer返还到Buffer队列中,供下次再申请。 | 22| OH_NativeWindow_NativeWindowHandleOpt (struct NativeWindow \*window, int code,...) | 设置/获取NativeWindow的属性,包括设置/获取宽高、内容格式等。 | 23| OH_NativeWindow_GetBufferHandleFromNative (struct NativeWindowBuffer \*buffer) | 通过NativeWindowBuffer获取该buffer的BufferHandle指针。 | 24| OH_NativeWindow_NativeObjectReference (void \*obj) | 增加一个NativeObject的引用计数。 | 25| OH_NativeWindow_NativeObjectUnreference (void \*obj) | 减少一个NativeObject的引用计数,当引用计数减少为0时,该NativeObject将被析构掉。 | 26| OH_NativeWindow_GetNativeObjectMagic (void \*obj) | 获取NativeObject的MagicId。 | 27 28详细的接口说明请参考[native_window](../reference/native-apis/_native_window.md)。 29 30## 开发步骤 31 32以下步骤描述了在**OpenHarmony**中如何利用`OH_NativeXComponent`通过`Native C++`代码绘制内容并显示在屏幕上。 33 341. **在页面中定义XComponent组件**,在`index.ets`中定义一个`texture`类型的`XComponent`,用于显示内容。 35 ```js 36 XComponent({ id: 'xcomponentId', type: 'texture', libraryname: 'nativerender'}) 37 .borderColor(Color.Red) 38 .borderWidth(5) 39 .onLoad(() => {}) 40 .onDestroy(() => {}) 41 ``` 42 432. **获取OH_NativeXComponent实例**。使用 `napi_get_named_property` 接口获取一个`OH_NativeXComponent`实例 `nativeXComponent`,通过注册该实例的回调接口获取`NativeWindow`实例。 44 45 ```c++ 46 // 定义 napi instance 47 napi_value exportInstance = nullptr; 48 // 定义一个 OH_NativeXComponent 实例 49 OH_NativeXComponent *nativeXComponent = nullptr; 50 // 通过 OH_NATIVE_XCOMPONENT_OBJ export 实例 51 napi_getname_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance); 52 // 将 napi instance 转化为 OH_NativeXComponent 实例 53 napi_unwarp(env, exportInstance, reinterpret_cast<void**>(&nativeXComponent)); 54 ``` 55 563. **定义回调函数OnSurfaceCreated**。用于在`Surface`创建时,通过回调函数初始化开发者的渲染环境,例如`Skia`渲染环境。并将要显示的内容写入`NativeWindow`: 57 58 ```c++ 59 void OnSufaceCreatedCB(NativeXComponent* component, void* window) { 60 //获取 native window 的宽高 61 uint64_t width_ = 0, height_ = 0; 62 OH_NativeXComponent_GetXComponentSize(nativeXComponent, window, &width_, &height_); 63 // 将void* 转换为 NativeWindow 实例,NativeWindow 定义在 native_window/external_window.h 中 64 NativeWindow* nativeWindow_ = (NativeWindow*)(window); 65 66 // 通过 OH_NativeWindow_NativeWindowHandleOpt 设置或者获取NativeWindow的属性 67 // 1.通过 SET_USAGE 设置 Native Window 的 usage 属性, 例如:HBM_USE_CPU_READ 68 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, HBM_USE_CPU_READ | HBM_USE_CPU_WRITE |HBM_USE_MEM_DMA); 69 // 2.通过 SET_BUFFER_GEOMETRY 设置 Native Window 的 宽高属性 70 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_BUFFER_GEOMETRY, width_, height_); 71 // 3.通过 SET_FORMAT 设置 Native Window 的 format 属性, 例如:PIXEL_FMT_RGBA_8888 72 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_FORMAT, PIXEL_FMT_RGBA_8888); 73 // 4.通过 SET_STRIDE 设置 Native Window 的 stride 属性 74 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_STRIDE, 0x8); 75 76 // 通过 OH_NativeWindow_NativeWindowRequestBuffer 获取 NativeWindowBuffer 实例 77 struct NativeWindowBuffer* buffer = nullptr; 78 int fenceFd; 79 OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow_, &buffer, &fenceFd); 80 81 // 通过 OH_NativeWindow_GetNativeBufferHandleFromNative 获取 buffer handle 82 BufferHandle* bufferHandle = OH_NativeWindow_GetNativeBufferHandleFromNative(buffer); 83 84 // 通过 BufferHandle 创建Skia Bitmap 85 SkBitmap bitmap; 86 SkImageInfo imageInfo = ... 87 bitmap.setInfo(imageInfo, bufferHandle->stride); 88 bitmap.setPixels(bufferHandle->virAddr); 89 //创建 Skia Canvas 并将内容写入native window 90 ... 91 92 //写入完成后,通过OH_NativeWindwo_NativeWindowFlushBuffer 提交给消费者使用,例如:显示在屏幕上 93 Regoin region{nullptr, 0}; 94 OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow_, buffer, fenceFd, region) 95 } 96 ``` 97 984. **注册回调函数OnSurfaceCreated等**。使用 `OH_NativeXComponent_RegisterCallback` 接口注册上一步中创建的回调函数。 99 100 ```c++ 101 OH_NativeXComponent_Callback &callback_; 102 callback_->OnSurfaceCreated = OnSufaceCreatedCB; 103 callback_->OnSurfaceChanged = OnSufaceChangedCB; 104 callback_->OnSurfaceDestroyed = OnSufaceDestroyedCB; 105 callback_->DispatchTouchEvent = DispatchTouchEventCB; 106 OH_NativeXComponent_RegisterCallback(nativeXComponent, callback_) 107 ``` 108 109## 相关实例 110 111针对NativeWindow的使用,有以下相关实例可供参考: 112 113- [使用NativeWindow接口获取Buffer](https://gitee.com/openharmony/graphic_graphic_2d/blob/master/rosen/samples/hello_native_window/hello_native_window.cpp)