native-window-guidelines.md 6.7 KB
Newer Older
Z
zengyawen 已提交
1
# NativeWindow开发指导
A
andrewhw 已提交
2 3 4

## 场景介绍

5
NativeWindow是`OpenHarmony`**本地平台化窗口**,表示图形队列的生产者端。开发者可以通过`NativeWindow`接口进行申请和提交`Buffer`,配置`Buffer`属性信息。
A
andrewhw 已提交
6 7
针对NativeWindow,常见的开发场景如下:

S
fix  
shegangbin 已提交
8
* 通过`NativeWindow`提供的Native API接口申请图形`Buffer`,并将生产图形内容写入图形`Buffer`,最终提交`Buffer`到图形队列
A
andrew0229 已提交
9
* 在适配EGL层的`eglswapbuffer`接口时,进行申请和提交`Buffer`
A
andrewhw 已提交
10 11 12 13 14

## 接口说明

| 接口名 | 描述 | 
| -------- | -------- |
15 16 17
| OH_NativeWindow_NativeWindowRequestBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*\*buffer, int \*fenceFd) | 通过OHNativeWindow对象申请一块OHNativeWindowBuffer,用以内容生产。 | 
| OH_NativeWindow_NativeWindowFlushBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*buffer, int fenceFd, Region region) | 通过OHNativeWindow将生产好内容的OHNativeWindowBuffer放回到Buffer队列中,用以内容消费。 | 
| OH_NativeWindow_NativeWindowHandleOpt (OHNativeWindow \*window, int code,...) | 设置/获取OHNativeWindow的属性,包括设置/获取宽高、内容格式等。 | 
A
andrewhw 已提交
18 19 20 21 22

详细的接口说明请参考[native_window](../reference/native-apis/_native_window.md)

## 开发步骤

S
fix  
shegangbin 已提交
23 24
以下步骤描述了在**OpenHarmony**中如何使用`NativeWindow`提供的Native API接口,申请图形`Buffer`,并将生产图形内容写入图形`Buffer`后,最终提交`Buffer`到图形队列。

S
shegangbin 已提交
25 26 27 28 29 30 31
**添加动态链接库**
CMakeLists.txt中添加以下lib。
```txt
libace_ndk.z.so
libnative_window.so
```

S
shegangbin 已提交
32
**头文件**
S
fix  
shegangbin 已提交
33
```c++
S
shegangbin 已提交
34
#include <ace/xcomponent/native_interface_xcomponent.h>
S
fix  
shegangbin 已提交
35 36
#include <native_window/external_window.h>
```
A
andrewhw 已提交
37

S
shegangbin 已提交
38 39 40 41
1. **获取OHNativeWindow实例**

    可在[`OH_NativeXComponent_Callback`](../reference/native-apis/_o_h___native_x_component___callback.md)提供的接口中获取OHNativeWindow,下面提供一份代码示例。XComponent模块的具体使用方法请参考[XComponent开发指导](xcomponent-guidelines.md)。
    1. 在xxx.ets中添加一个XComponent组件。
42
        ```ts
S
shegangbin 已提交
43 44 45
        XComponent({ id: 'xcomponentId', type: 'surface', libraryname: 'entry'})
            .width(360)
            .height(360)
46
        ```
S
shegangbin 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
    2. 在 native c++ 层获取 NativeXComponent。
        ```c++
        napi_value exportInstance = nullptr;
        // 用来解析出被wrap了NativeXComponent指针的属性
        napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);
        OH_NativeXComponent *nativeXComponent = nullptr;
        // 通过napi_unwrap接口,解析出NativeXComponent的实例指针
        napi_unwrap(env, exportInstance, reinterpret_cast<void**>(&nativeXComponent));
        ```
    3. 定义 OH_NativeXComponent_Callback。
        ```c++
        // 定义回调函数
        void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window)
        {
            // 可获取 OHNativeWindow 实例
            OHNativeWindow* nativeWindow = static_cast<OHNativeWindow*>(window);
            // ...
        }
        void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window)
        {
            // 可获取 OHNativeWindow 实例
            OHNativeWindow* nativeWindow = static_cast<OHNativeWindow*>(window);
            // ...
        }
        void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window)
        {
            // 可获取 OHNativeWindow 实例
            OHNativeWindow* nativeWindow = static_cast<OHNativeWindow*>(window);
            // ...
        }
        void DispatchTouchEventCB(OH_NativeXComponent* component, void* window)
        {
            // 可获取 OHNativeWindow 实例
            OHNativeWindow* nativeWindow = static_cast<OHNativeWindow*>(window);
            // ...
        }
        ```
        ```c++
        // 初始化 OH_NativeXComponent_Callback
        OH_NativeXComponent_Callback callback;
        callback.OnSurfaceCreated = OnSurfaceCreatedCB;
        callback.OnSurfaceChanged = OnSurfaceChangedCB;
        callback.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
        callback.DispatchTouchEvent = DispatchTouchEventCB;
91 92
        ```
   4. 将 OH_NativeXComponent_Callback 注册给 NativeXComponent。
S
shegangbin 已提交
93 94 95 96
        ```c++
        // 注册回调函数
        OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback);
        ```
A
andrewhw 已提交
97

S
fix  
shegangbin 已提交
98
2. **设置OHNativeWindowBuffer的属性**。使用`OH_NativeWindow_NativeWindowHandleOpt`设置`OHNativeWindowBuffer`的属性。
A
andrewhw 已提交
99
    ```c++
S
fix  
shegangbin 已提交
100
    // 设置 OHNativeWindowBuffer 的宽高
S
shegangbin 已提交
101
    int32_t code = SET_BUFFER_GEOMETRY;
A
andrew0229 已提交
102 103
    int32_t width = 0x100;
    int32_t height = 0x100;
S
shegangbin 已提交
104 105
    // 这里的nativeWindow是从上一步骤中的回调函数中获得的
    int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height);
S
fix  
shegangbin 已提交
106
    // 设置 OHNativeWindowBuffer 的步长
A
andrew0229 已提交
107 108 109
    code = SET_STRIDE;
    int32_t stride = 0x8;
    ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, stride);
A
andrewhw 已提交
110 111
    ```

S
fix  
shegangbin 已提交
112
3. **从图形队列申请OHNativeWindowBuffer**
A
andrew0229 已提交
113
    ```c++
S
fix  
shegangbin 已提交
114
    OHNativeWindowBuffer* buffer = nullptr;
A
andrew0229 已提交
115
    int fenceFd;
S
fix  
shegangbin 已提交
116
    // 通过 OH_NativeWindow_NativeWindowRequestBuffer 获取 OHNativeWindowBuffer 实例
S
shegangbin 已提交
117 118 119
    OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd);
    // 通过 OH_NativeWindow_GetBufferHandleFromNative 获取 buffer 的 handle
    BufferHandle* bufferHandle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
A
andrew0229 已提交
120
    ```
A
andrewhw 已提交
121

S
shegangbin 已提交
122 123 124 125 126 127 128 129 130 131 132 133
4. **内存映射mmap**
    ```c++
    #include <sys/mman.h>

    // 使用系统mmap接口拿到bufferHandle的内存虚拟地址
    void* mappedAddr = mmap(bufferHandle->virAddr, bufferHandle->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0);
    if (mappedAddr == MAP_FAILED) {
        // mmap failed
    }
    ```

5. **将生产的内容写入OHNativeWindowBuffer**
A
andrewhw 已提交
134
    ```c++
A
andrew0229 已提交
135 136
    static uint32_t value = 0x00;
    value++;
S
shegangbin 已提交
137
    uint32_t *pixel = static_cast<uint32_t *>(mappedAddr); // 使用mmap获取到的地址来访问内存
A
andrew0229 已提交
138 139 140 141
    for (uint32_t x = 0; x < width; x++) {
        for (uint32_t y = 0;  y < height; y++) {
            *pixel++ = value;
        }
A
andrewhw 已提交
142 143 144
    }
    ```

S
fix  
shegangbin 已提交
145
5. **提交OHNativeWindowBuffer到图形队列**
A
andrewhw 已提交
146
    ```c++
S
fix  
shegangbin 已提交
147
    // 设置刷新区域,如果Region中的Rect为nullptr,或者rectNumber为0,则认为OHNativeWindowBuffer全部有内容更改。
A
andrew0229 已提交
148 149
    Region region{nullptr, 0};
    // 通过OH_NativeWindow_NativeWindowFlushBuffer 提交给消费者使用,例如:显示在屏幕上。
S
shegangbin 已提交
150 151 152 153 154 155 156 157 158
    OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region);
    ```
6. **取消内存映射munmap**
    ```c++
    // 内存使用完记得去掉内存映射
    int result = munmap(mappedAddr, bufferHandle->size);
    if (result == -1) {
        // munmap failed
    }
A
andrewhw 已提交
159
    ```