1e41f4b71Sopenharmony_ci# Native Window Development (C/C++)
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## When to Use
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ciThe native window module is a local platform-based window that represents the producer of a graphics queue. It provides APIs for you to request and flush a buffer and configure buffer attributes.
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciThe following scenarios are common for native window development:
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci* Request a graphics buffer by using the native window API, write the produced graphics content to the buffer, and flush the buffer to the graphics queue.
10e41f4b71Sopenharmony_ci* Request and flush a buffer when adapting to the **eglswapbuffer** interface at the EGL.
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ci## Available APIs
13e41f4b71Sopenharmony_ci
14e41f4b71Sopenharmony_ci| API| Description| 
15e41f4b71Sopenharmony_ci| -------- | -------- |
16e41f4b71Sopenharmony_ci| OH_NativeWindow_NativeWindowRequestBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*\*buffer, int \*fenceFd) | Requests an **OHNativeWindowBuffer** through an **OHNativeWindow** instance for content production.| 
17e41f4b71Sopenharmony_ci| OH_NativeWindow_NativeWindowFlushBuffer (OHNativeWindow \*window, OHNativeWindowBuffer \*buffer, int fenceFd, Region region) | Flushes the **OHNativeWindowBuffer** filled with the produced content to the buffer queue through an **OHNativeWindow** instance for content consumption.| 
18e41f4b71Sopenharmony_ci| OH_NativeWindow_NativeWindowHandleOpt (OHNativeWindow \*window, int code,...) | Sets or obtains the attributes of an **OHNativeWindow** instance, including the width, height, and content format.| 
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ciFor details about the APIs, see [native_window](../reference/apis-arkgraphics2d/_native_window.md).
21e41f4b71Sopenharmony_ci
22e41f4b71Sopenharmony_ci## How to Develop
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ciThe following describes how to use the native window APIs to request a graphics buffer, write the produced graphics content to the buffer, and flush the buffer to the graphics queue.
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci**Adding Dynamic Link Libraries**
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ciAdd the following libraries to **CMakeLists.txt**:
29e41f4b71Sopenharmony_ci```txt
30e41f4b71Sopenharmony_cilibace_ndk.z.so
31e41f4b71Sopenharmony_cilibnative_window.so
32e41f4b71Sopenharmony_ci```
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci**Including Header Files**
35e41f4b71Sopenharmony_ci```c++
36e41f4b71Sopenharmony_ci#include <sys/poll.h>
37e41f4b71Sopenharmony_ci#include <sys/mman.h>
38e41f4b71Sopenharmony_ci#include <unistd.h>
39e41f4b71Sopenharmony_ci#include <ace/xcomponent/native_interface_xcomponent.h>
40e41f4b71Sopenharmony_ci#include <native_window/external_window.h>
41e41f4b71Sopenharmony_ci```
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci1. Obtain an **OHNativeWindow** instance.
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ci    You can call the APIs provided by [OH_NativeXComponent_Callback](../reference/apis-arkui/_o_h___native_x_component___callback.md) to obtain an **OHNativeWindow** instance. An example code snippet is provided below. For details about how to use the **XComponent**, see [XComponent Development](../ui/napi-xcomponent-guidelines.md).
46e41f4b71Sopenharmony_ci    1. Add an **XComponent** to the .ets file.
47e41f4b71Sopenharmony_ci        ```ts
48e41f4b71Sopenharmony_ci        XComponent({ id: 'xcomponentId', type: 'surface', libraryname: 'entry'})
49e41f4b71Sopenharmony_ci            .width(360)
50e41f4b71Sopenharmony_ci            .height(360)
51e41f4b71Sopenharmony_ci        ```
52e41f4b71Sopenharmony_ci    2. Obtain **NativeXComponent** at the native C++ layer.
53e41f4b71Sopenharmony_ci        ```c++
54e41f4b71Sopenharmony_ci        napi_value exportInstance = nullptr;
55e41f4b71Sopenharmony_ci        // Parse the attribute of the wrapped NativeXComponent pointer.
56e41f4b71Sopenharmony_ci        napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);
57e41f4b71Sopenharmony_ci        OH_NativeXComponent *nativeXComponent = nullptr;
58e41f4b71Sopenharmony_ci        // Use the napi_unwrap API to parse the NativeXComponent instance pointer.
59e41f4b71Sopenharmony_ci        napi_unwrap(env, exportInstance, reinterpret_cast<void**>(&nativeXComponent));
60e41f4b71Sopenharmony_ci        // Obtain the XComponent ID.
61e41f4b71Sopenharmony_ci        char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
62e41f4b71Sopenharmony_ci        uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
63e41f4b71Sopenharmony_ci        OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize);
64e41f4b71Sopenharmony_ci        ```
65e41f4b71Sopenharmony_ci    3. Define **OH_NativeXComponent_Callback**.
66e41f4b71Sopenharmony_ci        ```c++
67e41f4b71Sopenharmony_ci        // Define the callback.
68e41f4b71Sopenharmony_ci        void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window)
69e41f4b71Sopenharmony_ci        {
70e41f4b71Sopenharmony_ci            // Obtain an OHNativeWindow instance.
71e41f4b71Sopenharmony_ci            OHNativeWindow* nativeWindow = static_cast<OHNativeWindow*>(window);
72e41f4b71Sopenharmony_ci            // After this callback is triggered, the reference count for the window is initialized to 1. If the window-related APIs and XComponent destructor are concurrently used,
73e41f4b71Sopenharmony_ci            // you must manually adjust the reference count by using OH_NativeWindow_NativeObjectReference to increase it and OH_NativeWindow_NativeObjectUnreference to decrease it.
74e41f4b71Sopenharmony_ci            // This manual management of the reference count by 1 helps to avoid issues with dangling or null pointers that could occur during concurrent calls to window APIs following the destruction of an XComponent.
75e41f4b71Sopenharmony_ci        }
76e41f4b71Sopenharmony_ci        void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window)
77e41f4b71Sopenharmony_ci        {
78e41f4b71Sopenharmony_ci            // Obtain an OHNativeWindow instance.
79e41f4b71Sopenharmony_ci            OHNativeWindow* nativeWindow = static_cast<OHNativeWindow*>(window);
80e41f4b71Sopenharmony_ci            // ...
81e41f4b71Sopenharmony_ci        }
82e41f4b71Sopenharmony_ci        void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window)
83e41f4b71Sopenharmony_ci        {
84e41f4b71Sopenharmony_ci            // Obtain an OHNativeWindow instance.
85e41f4b71Sopenharmony_ci            OHNativeWindow* nativeWindow = static_cast<OHNativeWindow*>(window);
86e41f4b71Sopenharmony_ci            // After this callback is triggered, the reference count for the window is decremented by 1. When the reference count reaches 0, the window is destructed.
87e41f4b71Sopenharmony_ci            // Once the window is destructed, no further API calls should be made through the window. This operation results in a crash caused by dangling or null pointers.
88e41f4b71Sopenharmony_ci        }
89e41f4b71Sopenharmony_ci        void DispatchTouchEventCB(OH_NativeXComponent* component, void* window)
90e41f4b71Sopenharmony_ci        {
91e41f4b71Sopenharmony_ci            // Obtain an OHNativeWindow instance.
92e41f4b71Sopenharmony_ci            OHNativeWindow* nativeWindow = static_cast<OHNativeWindow*>(window);
93e41f4b71Sopenharmony_ci            // ...
94e41f4b71Sopenharmony_ci        }
95e41f4b71Sopenharmony_ci        ```
96e41f4b71Sopenharmony_ci        ```c++
97e41f4b71Sopenharmony_ci        // Initialize OH_NativeXComponent_Callback.
98e41f4b71Sopenharmony_ci        OH_NativeXComponent_Callback callback;
99e41f4b71Sopenharmony_ci        callback.OnSurfaceCreated = OnSurfaceCreatedCB;
100e41f4b71Sopenharmony_ci        callback.OnSurfaceChanged = OnSurfaceChangedCB;
101e41f4b71Sopenharmony_ci        callback.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
102e41f4b71Sopenharmony_ci        callback.DispatchTouchEvent = DispatchTouchEventCB;
103e41f4b71Sopenharmony_ci        ```
104e41f4b71Sopenharmony_ci   4. Register **OH_NativeXComponent_Callback** with **NativeXComponent**.
105e41f4b71Sopenharmony_ci        ```c++
106e41f4b71Sopenharmony_ci        // Register the callback.
107e41f4b71Sopenharmony_ci        OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback);
108e41f4b71Sopenharmony_ci        ```
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ci2. Set the attributes of an **OHNativeWindowBuffer** by using **OH_NativeWindow_NativeWindowHandleOpt**.
111e41f4b71Sopenharmony_ci    ```c++
112e41f4b71Sopenharmony_ci    // Set the width and height of the OHNativeWindowBuffer.
113e41f4b71Sopenharmony_ci    int32_t code = SET_BUFFER_GEOMETRY;
114e41f4b71Sopenharmony_ci    int32_t width = 0x100;
115e41f4b71Sopenharmony_ci    int32_t height = 0x100;
116e41f4b71Sopenharmony_ci    // The nativeWindow instance is obtained from the callback in the previous step.
117e41f4b71Sopenharmony_ci    int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height);
118e41f4b71Sopenharmony_ci    ```
119e41f4b71Sopenharmony_ci
120e41f4b71Sopenharmony_ci3. Request an **OHNativeWindowBuffer** from the graphics queue.
121e41f4b71Sopenharmony_ci    ```c++
122e41f4b71Sopenharmony_ci    OHNativeWindowBuffer* buffer = nullptr;
123e41f4b71Sopenharmony_ci    int releaseFenceFd = -1;
124e41f4b71Sopenharmony_ci    // Obtain the OHNativeWindowBuffer instance by calling OH_NativeWindow_NativeWindowRequestBuffer.
125e41f4b71Sopenharmony_ci    ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &releaseFenceFd);
126e41f4b71Sopenharmony_ci    if (ret != 0 || buffer == nullptr) {
127e41f4b71Sopenharmony_ci        return;
128e41f4b71Sopenharmony_ci    }
129e41f4b71Sopenharmony_ci    // Obtain the buffer handle by calling OH_NativeWindow_GetBufferHandleFromNative.
130e41f4b71Sopenharmony_ci    BufferHandle* bufferHandle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
131e41f4b71Sopenharmony_ci    ```
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ci4. Map memory.
134e41f4b71Sopenharmony_ci    ```c++
135e41f4b71Sopenharmony_ci    #include <sys/mman.h>
136e41f4b71Sopenharmony_ci
137e41f4b71Sopenharmony_ci    // Use mmap() to map the shared memory allocated to the buffer handle to the user space. Image data can be written to the buffer handle by using the obtained virtual address.
138e41f4b71Sopenharmony_ci    // bufferHandle->virAddr indicates the start address of the buffer handle in the shared memory, and bufferHandle->size indicates the memory usage of the buffer handle in the shared memory.
139e41f4b71Sopenharmony_ci    void* mappedAddr = mmap(bufferHandle->virAddr, bufferHandle->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0);
140e41f4b71Sopenharmony_ci    if (mappedAddr == MAP_FAILED) {
141e41f4b71Sopenharmony_ci        // mmap failed
142e41f4b71Sopenharmony_ci    }
143e41f4b71Sopenharmony_ci    ```
144e41f4b71Sopenharmony_ci
145e41f4b71Sopenharmony_ci5. Write the produced content to the **OHNativeWindowBuffer**.
146e41f4b71Sopenharmony_ci
147e41f4b71Sopenharmony_ci   Before this operation, wait until **releaseFenceFd** is available. (Note that **poll** needs to be called only when **releaseFenceFd** is not **-1**.) If no data waiting for **releaseFenceFd** is available (POLLIN), problems such as artifacts, cracks, and High Efficiency Bandwidth Compression (HEBC) faults may occur. **releaseFenceFd** is a file handle created by the consumer process to indicate that the consumer has consumed the buffer, the buffer is readable, and the producer can start to fill in the buffer.
148e41f4b71Sopenharmony_ci    ```c++
149e41f4b71Sopenharmony_ci    int retCode = -1;
150e41f4b71Sopenharmony_ci    uint32_t timeout = 3000;
151e41f4b71Sopenharmony_ci    if (releaseFenceFd != -1) {
152e41f4b71Sopenharmony_ci        struct pollfd pollfds = {0};
153e41f4b71Sopenharmony_ci        pollfds.fd = releaseFenceFd;
154e41f4b71Sopenharmony_ci        pollfds.events = POLLIN;
155e41f4b71Sopenharmony_ci        do {
156e41f4b71Sopenharmony_ci            retCode = poll(&pollfds, 1, timeout);
157e41f4b71Sopenharmony_ci        } while (retCode == -1 && (errno == EINTR || errno == EAGAIN));
158e41f4b71Sopenharmony_ci        close(releaseFenceFd); // Prevent FD leakage.
159e41f4b71Sopenharmony_ci    }
160e41f4b71Sopenharmony_ci
161e41f4b71Sopenharmony_ci    static uint32_t value = 0x00;
162e41f4b71Sopenharmony_ci    value++;
163e41f4b71Sopenharmony_ci    uint32_t *pixel = static_cast<uint32_t *>(mappedAddr); // Use the address obtained by mmap() to access the memory.
164e41f4b71Sopenharmony_ci    for (uint32_t x = 0; x < width; x++) {
165e41f4b71Sopenharmony_ci        for (uint32_t y = 0;  y < height; y++) {
166e41f4b71Sopenharmony_ci            *pixel++ = value;
167e41f4b71Sopenharmony_ci        }
168e41f4b71Sopenharmony_ci    }
169e41f4b71Sopenharmony_ci    ```
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci5. Flush the **OHNativeWindowBuffer** to the graphics queue.
172e41f4b71Sopenharmony_ci
173e41f4b71Sopenharmony_ci   Note that **acquireFenceFd** of **OH_NativeWindow_NativeWindowFlushBuffer** cannot be the same as **releaseFenceFd** obtained by **OH_NativeWindow_NativeWindowRequestBuffer**. **acquireFenceFd** is the file handle passed in by the producer, and the default value **-1** can be passed. Based on **acquireFenceFd**, the consumer, after obtaining the buffer, determines when to render and display the buffered content.
174e41f4b71Sopenharmony_ci    ```c++
175e41f4b71Sopenharmony_ci    // Set the refresh region. If Rect in Region is a null pointer or rectNumber is 0, all contents in the OHNativeWindowBuffer are changed.
176e41f4b71Sopenharmony_ci    Region region{nullptr, 0};
177e41f4b71Sopenharmony_ci    int acquireFenceFd = -1;
178e41f4b71Sopenharmony_ci    // Flush the buffer to the consumer through OH_NativeWindow_NativeWindowFlushBuffer, for example, by displaying it on the screen.
179e41f4b71Sopenharmony_ci    OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, acquireFenceFd, region);
180e41f4b71Sopenharmony_ci    ```
181e41f4b71Sopenharmony_ci6. Unmap memory.
182e41f4b71Sopenharmony_ci    ```c++
183e41f4b71Sopenharmony_ci    // Unmap the memory when the memory is no longer required.
184e41f4b71Sopenharmony_ci    int result = munmap(mappedAddr, bufferHandle->size);
185e41f4b71Sopenharmony_ci    if (result == -1) {
186e41f4b71Sopenharmony_ci        // munmap failed
187e41f4b71Sopenharmony_ci    }
188e41f4b71Sopenharmony_ci    ```
189e41f4b71Sopenharmony_ci
190