native-window-guidelines.md 6.8 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
**添加动态链接库**
S
shegangbin 已提交
26

S
shegangbin 已提交
27 28 29 30 31 32
CMakeLists.txt中添加以下lib。
```txt
libace_ndk.z.so
libnative_window.so
```

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

S
shegangbin 已提交
39 40 41 42
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组件。
43
        ```ts
S
shegangbin 已提交
44 45 46
        XComponent({ id: 'xcomponentId', type: 'surface', libraryname: 'entry'})
            .width(360)
            .height(360)
47
        ```
S
shegangbin 已提交
48 49 50 51 52 53 54 55
    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));
S
shegangbin 已提交
56 57 58 59
        // 获取XComponentId
        char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
        uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
        OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize);
S
shegangbin 已提交
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 91 92 93 94 95
        ```
    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;
96 97
        ```
   4. 将 OH_NativeXComponent_Callback 注册给 NativeXComponent。
S
shegangbin 已提交
98 99 100 101
        ```c++
        // 注册回调函数
        OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback);
        ```
A
andrewhw 已提交
102

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

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

S
shegangbin 已提交
123 124 125 126 127 128 129 130 131 132 133 134
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 已提交
135
    ```c++
A
andrew0229 已提交
136 137
    static uint32_t value = 0x00;
    value++;
S
shegangbin 已提交
138
    uint32_t *pixel = static_cast<uint32_t *>(mappedAddr); // 使用mmap获取到的地址来访问内存
A
andrew0229 已提交
139 140 141 142
    for (uint32_t x = 0; x < width; x++) {
        for (uint32_t y = 0;  y < height; y++) {
            *pixel++ = value;
        }
A
andrewhw 已提交
143 144 145
    }
    ```

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