1e41f4b71Sopenharmony_ci# Native Image Development (C/C++) 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## When to Use 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ciThe native image module is used for associating a surface with an OpenGL external texture. It functions as the consumer of a graphics queue. You can use the APIs of this module to obtain and use a buffer, and output the buffer content to an OpenGL external texture. 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciThe following scenario is common for native image development: 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciUse the native image APIs to create an **OH_NativeImage** instance as the consumer and obtain the corresponding **OHNativeWindow** instance (functioning as the producer). Use the native window APIs to fill in and flush the buffer, and then use the native image APIs to update the buffer content to an OpenGL ES texture. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ciThe native image module must be used together with the native window, native buffer, EGL, and GLES3 modules. 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci## Available APIs 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci| API | Description | 16e41f4b71Sopenharmony_ci| ------------------------------------------------------------ | ------------------------------------------------------------ | 17e41f4b71Sopenharmony_ci| OH_NativeImage_Create (uint32_t textureId, uint32_t textureTarget) | Creates an **OH_NativeImage** instance to be associated with the specified OpenGL ES texture ID and target.| 18e41f4b71Sopenharmony_ci| OH_NativeImage_AcquireNativeWindow (OH_NativeImage \*image) | Obtains an **OHNativeWindow** instance associated with an **OH_NativeImage** instance. You need to call **OH_NativeWindow_DestroyNativeWindow** to release the **OHNativeWindow** instance when it is no longer needed.| 19e41f4b71Sopenharmony_ci| OH_NativeImage_AttachContext (OH_NativeImage \*image, uint32_t textureId) | Attaches an **OH_NativeImage** instance to the current OpenGL ES context. The OpenGL ES texture will be bound to an **GL_TEXTURE_EXTERNAL_OES** instance and updated through the **OH_NativeImage** instance.| 20e41f4b71Sopenharmony_ci| OH_NativeImage_DetachContext (OH_NativeImage \*image) | Detaches an **OH_NativeImage** instance from the current OpenGL ES context. | 21e41f4b71Sopenharmony_ci| OH_NativeImage_UpdateSurfaceImage (OH_NativeImage \*image) | Updates the OpenGL ES texture associated with the latest frame through an **OH_NativeImage** instance. | 22e41f4b71Sopenharmony_ci| OH_NativeImage_GetTimestamp (OH_NativeImage \*image) | Obtains the timestamp of the texture image that recently called the **OH_NativeImage_UpdateSurfaceImage** function.| 23e41f4b71Sopenharmony_ci| OH_NativeImage_GetTransformMatrix (OH_NativeImage \*image, float matrix[16]) | Obtains the transformation matrix of the texture image that recently called the **OH_NativeImage_UpdateSurfaceImage** function.| 24e41f4b71Sopenharmony_ci| OH_NativeImage_Destroy (OH_NativeImage \*\*image) | Destroys an **OH_NativeImage** instance created by calling **OH_NativeImage_Create**. After the instance is destroyed, the pointer to it is assigned **NULL**.| 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ciFor details about the APIs, see [native_image](../reference/apis-arkgraphics2d/_o_h___native_image.md). 27e41f4b71Sopenharmony_ci 28e41f4b71Sopenharmony_ci## How to Develop 29e41f4b71Sopenharmony_ci 30e41f4b71Sopenharmony_ciThe following steps describe how to use the native Image APIs to create an **OH_NativeImage** instance as the consumer and update the data to a OpenGL external texture. 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ci**Adding Dynamic Link Libraries** 33e41f4b71Sopenharmony_ci 34e41f4b71Sopenharmony_ciAdd the following libraries to **CMakeLists.txt**: 35e41f4b71Sopenharmony_ci 36e41f4b71Sopenharmony_ci```txt 37e41f4b71Sopenharmony_cilibEGL.so 38e41f4b71Sopenharmony_cilibGLESv3.so 39e41f4b71Sopenharmony_cilibnative_image.so 40e41f4b71Sopenharmony_cilibnative_window.so 41e41f4b71Sopenharmony_cilibnative_buffer.so 42e41f4b71Sopenharmony_ci``` 43e41f4b71Sopenharmony_ci 44e41f4b71Sopenharmony_ci**Including Header Files** 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ci```c++ 47e41f4b71Sopenharmony_ci#include <iostream> 48e41f4b71Sopenharmony_ci#include <string> 49e41f4b71Sopenharmony_ci#include <EGL/egl.h> 50e41f4b71Sopenharmony_ci#include <EGL/eglext.h> 51e41f4b71Sopenharmony_ci#include <GLES3/gl3.h> 52e41f4b71Sopenharmony_ci#include <GLES2/gl2ext.h> 53e41f4b71Sopenharmony_ci#include <sys/mman.h> 54e41f4b71Sopenharmony_ci#include <native_image/native_image.h> 55e41f4b71Sopenharmony_ci#include <native_window/external_window.h> 56e41f4b71Sopenharmony_ci#include <native_buffer/native_buffer.h> 57e41f4b71Sopenharmony_ci``` 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci1. Initialize the EGL environment. 60e41f4b71Sopenharmony_ci 61e41f4b71Sopenharmony_ci Refer to the code snippet below. For details about how to use the **\<XComponent>**, see [XComponent Development](../ui/napi-xcomponent-guidelines.md). 62e41f4b71Sopenharmony_ci ```c++ 63e41f4b71Sopenharmony_ci using GetPlatformDisplayExt = PFNEGLGETPLATFORMDISPLAYEXTPROC; 64e41f4b71Sopenharmony_ci constexpr const char *EGL_EXT_PLATFORM_WAYLAND = "EGL_EXT_platform_wayland"; 65e41f4b71Sopenharmony_ci constexpr const char *EGL_KHR_PLATFORM_WAYLAND = "EGL_KHR_platform_wayland"; 66e41f4b71Sopenharmony_ci constexpr int32_t EGL_CONTEXT_CLIENT_VERSION_NUM = 2; 67e41f4b71Sopenharmony_ci constexpr char CHARACTER_WHITESPACE = ' '; 68e41f4b71Sopenharmony_ci constexpr const char *CHARACTER_STRING_WHITESPACE = " "; 69e41f4b71Sopenharmony_ci constexpr const char *EGL_GET_PLATFORM_DISPLAY_EXT = "eglGetPlatformDisplayEXT"; 70e41f4b71Sopenharmony_ci EGLContext eglContext_ = EGL_NO_CONTEXT; 71e41f4b71Sopenharmony_ci EGLDisplay eglDisplay_ = EGL_NO_DISPLAY; 72e41f4b71Sopenharmony_ci static inline EGLConfig config_; 73e41f4b71Sopenharmony_ci static inline EGLSurface eglSurface_; 74e41f4b71Sopenharmony_ci // OHNativeWindow obtained from the <XComponent>. 75e41f4b71Sopenharmony_ci OHNativeWindow *eglNativeWindow_; 76e41f4b71Sopenharmony_ci 77e41f4b71Sopenharmony_ci // Check the EGL extension. 78e41f4b71Sopenharmony_ci static bool CheckEglExtension(const char *extensions, const char *extension) { 79e41f4b71Sopenharmony_ci size_t extlen = strlen(extension); 80e41f4b71Sopenharmony_ci const char *end = extensions + strlen(extensions); 81e41f4b71Sopenharmony_ci 82e41f4b71Sopenharmony_ci while (extensions < end) { 83e41f4b71Sopenharmony_ci size_t n = 0; 84e41f4b71Sopenharmony_ci if (*extensions == CHARACTER_WHITESPACE) { 85e41f4b71Sopenharmony_ci extensions++; 86e41f4b71Sopenharmony_ci continue; 87e41f4b71Sopenharmony_ci } 88e41f4b71Sopenharmony_ci n = strcspn(extensions, CHARACTER_STRING_WHITESPACE); 89e41f4b71Sopenharmony_ci if (n == extlen && strncmp(extension, extensions, n) == 0) { 90e41f4b71Sopenharmony_ci return true; 91e41f4b71Sopenharmony_ci } 92e41f4b71Sopenharmony_ci extensions += n; 93e41f4b71Sopenharmony_ci } 94e41f4b71Sopenharmony_ci return false; 95e41f4b71Sopenharmony_ci } 96e41f4b71Sopenharmony_ci 97e41f4b71Sopenharmony_ci // Obtain the display. 98e41f4b71Sopenharmony_ci static EGLDisplay GetPlatformEglDisplay(EGLenum platform, void *native_display, const EGLint *attrib_list) { 99e41f4b71Sopenharmony_ci static GetPlatformDisplayExt eglGetPlatformDisplayExt = NULL; 100e41f4b71Sopenharmony_ci 101e41f4b71Sopenharmony_ci if (!eglGetPlatformDisplayExt) { 102e41f4b71Sopenharmony_ci const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); 103e41f4b71Sopenharmony_ci if (extensions && (CheckEglExtension(extensions, EGL_EXT_PLATFORM_WAYLAND) || 104e41f4b71Sopenharmony_ci CheckEglExtension(extensions, EGL_KHR_PLATFORM_WAYLAND))) { 105e41f4b71Sopenharmony_ci eglGetPlatformDisplayExt = (GetPlatformDisplayExt)eglGetProcAddress(EGL_GET_PLATFORM_DISPLAY_EXT); 106e41f4b71Sopenharmony_ci } 107e41f4b71Sopenharmony_ci } 108e41f4b71Sopenharmony_ci 109e41f4b71Sopenharmony_ci if (eglGetPlatformDisplayExt) { 110e41f4b71Sopenharmony_ci return eglGetPlatformDisplayExt(platform, native_display, attrib_list); 111e41f4b71Sopenharmony_ci } 112e41f4b71Sopenharmony_ci 113e41f4b71Sopenharmony_ci return eglGetDisplay((EGLNativeDisplayType)native_display); 114e41f4b71Sopenharmony_ci } 115e41f4b71Sopenharmony_ci 116e41f4b71Sopenharmony_ci static void InitEGLEnv() { 117e41f4b71Sopenharmony_ci // Obtain the display. 118e41f4b71Sopenharmony_ci eglDisplay_ = GetPlatformEglDisplay(EGL_PLATFORM_OHOS_KHR, EGL_DEFAULT_DISPLAY, NULL); 119e41f4b71Sopenharmony_ci if (eglDisplay_ == EGL_NO_DISPLAY) { 120e41f4b71Sopenharmony_ci std::cout << "Failed to create EGLDisplay gl errno : " << eglGetError() << std::endl; 121e41f4b71Sopenharmony_ci } 122e41f4b71Sopenharmony_ci 123e41f4b71Sopenharmony_ci EGLint major, minor; 124e41f4b71Sopenharmony_ci // Initialize the EGL display. 125e41f4b71Sopenharmony_ci if (eglInitialize(eglDisplay_, &major, &minor) == EGL_FALSE) { 126e41f4b71Sopenharmony_ci std::cout << "Failed to initialize EGLDisplay" << std::endl; 127e41f4b71Sopenharmony_ci } 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci // Bind the OpenGL ES API. 130e41f4b71Sopenharmony_ci if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) { 131e41f4b71Sopenharmony_ci std::cout << "Failed to bind OpenGL ES API" << std::endl; 132e41f4b71Sopenharmony_ci } 133e41f4b71Sopenharmony_ci 134e41f4b71Sopenharmony_ci unsigned int glRet; 135e41f4b71Sopenharmony_ci EGLint count; 136e41f4b71Sopenharmony_ci EGLint config_attribs[] = {EGL_SURFACE_TYPE, 137e41f4b71Sopenharmony_ci EGL_WINDOW_BIT, 138e41f4b71Sopenharmony_ci EGL_RED_SIZE, 139e41f4b71Sopenharmony_ci 8, 140e41f4b71Sopenharmony_ci EGL_GREEN_SIZE, 141e41f4b71Sopenharmony_ci 8, 142e41f4b71Sopenharmony_ci EGL_BLUE_SIZE, 143e41f4b71Sopenharmony_ci 8, 144e41f4b71Sopenharmony_ci EGL_ALPHA_SIZE, 145e41f4b71Sopenharmony_ci 8, 146e41f4b71Sopenharmony_ci EGL_RENDERABLE_TYPE, 147e41f4b71Sopenharmony_ci EGL_OPENGL_ES3_BIT, 148e41f4b71Sopenharmony_ci EGL_NONE}; 149e41f4b71Sopenharmony_ci 150e41f4b71Sopenharmony_ci // Obtain a valid system configuration. 151e41f4b71Sopenharmony_ci glRet = eglChooseConfig(eglDisplay_, config_attribs, &config_, 1, &count); 152e41f4b71Sopenharmony_ci if (!(glRet && static_cast<unsigned int>(count) >= 1)) { 153e41f4b71Sopenharmony_ci std::cout << "Failed to eglChooseConfig" << std::endl; 154e41f4b71Sopenharmony_ci } 155e41f4b71Sopenharmony_ci 156e41f4b71Sopenharmony_ci static const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION_NUM, EGL_NONE}; 157e41f4b71Sopenharmony_ci 158e41f4b71Sopenharmony_ci // Create a context. 159e41f4b71Sopenharmony_ci eglContext_ = eglCreateContext(eglDisplay_, config_, EGL_NO_CONTEXT, context_attribs); 160e41f4b71Sopenharmony_ci if (eglContext_ == EGL_NO_CONTEXT) { 161e41f4b71Sopenharmony_ci std::cout << "Failed to create egl context %{public}x, error:" << eglGetError() << std::endl; 162e41f4b71Sopenharmony_ci } 163e41f4b71Sopenharmony_ci 164e41f4b71Sopenharmony_ci // Create an eglSurface. 165e41f4b71Sopenharmony_ci eglSurface_ = eglCreateWindowSurface(eglDisplay_, config_, reinterpret_cast<EGLNativeWindowType>(eglNativeWindow_), context_attribs); 166e41f4b71Sopenharmony_ci if (eglSurface_ == EGL_NO_SURFACE) { 167e41f4b71Sopenharmony_ci std::cout << "Failed to create egl surface %{public}x, error:" << eglGetError() << std::endl; 168e41f4b71Sopenharmony_ci } 169e41f4b71Sopenharmony_ci 170e41f4b71Sopenharmony_ci // Associate the context. 171e41f4b71Sopenharmony_ci eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_); 172e41f4b71Sopenharmony_ci 173e41f4b71Sopenharmony_ci // The EGL environment initialization is complete. 174e41f4b71Sopenharmony_ci std::cout << "Create EGL context successfully, version" << major << "." << minor << std::endl; 175e41f4b71Sopenharmony_ci } 176e41f4b71Sopenharmony_ci ``` 177e41f4b71Sopenharmony_ci 178e41f4b71Sopenharmony_ci2. Create an **OH_NativeImage** instance. 179e41f4b71Sopenharmony_ci 180e41f4b71Sopenharmony_ci ```c++ 181e41f4b71Sopenharmony_ci // Create an OpenGL ES texture. 182e41f4b71Sopenharmony_ci GLuint textureId; 183e41f4b71Sopenharmony_ci glGenTextures(1, &textureId); 184e41f4b71Sopenharmony_ci // Create an OH_NativeImage instance, which will be associated with an OpenGL ES texture. 185e41f4b71Sopenharmony_ci OH_NativeImage* image = OH_NativeImage_Create(textureId, GL_TEXTURE_EXTERNAL_OES); 186e41f4b71Sopenharmony_ci ``` 187e41f4b71Sopenharmony_ci 188e41f4b71Sopenharmony_ci3. Obtain the **OHNativeWindow** instance that functions as the producer. 189e41f4b71Sopenharmony_ci 190e41f4b71Sopenharmony_ci ```c++ 191e41f4b71Sopenharmony_ci // Obtain an OHNativeWindow instance. 192e41f4b71Sopenharmony_ci OHNativeWindow* nativeWindow = OH_NativeImage_AcquireNativeWindow(image); 193e41f4b71Sopenharmony_ci ``` 194e41f4b71Sopenharmony_ci 195e41f4b71Sopenharmony_ci4. Set the width and height of the **OHNativeWindow** instance. 196e41f4b71Sopenharmony_ci 197e41f4b71Sopenharmony_ci ```c++ 198e41f4b71Sopenharmony_ci int code = SET_BUFFER_GEOMETRY; 199e41f4b71Sopenharmony_ci int32_t width = 800; 200e41f4b71Sopenharmony_ci int32_t height = 600; 201e41f4b71Sopenharmony_ci int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height); 202e41f4b71Sopenharmony_ci ``` 203e41f4b71Sopenharmony_ci 204e41f4b71Sopenharmony_ci5. Write the produced content to an **OHNativeWindowBuffer** instance. 205e41f4b71Sopenharmony_ci 206e41f4b71Sopenharmony_ci 1. Obtain an **OHNativeWindowBuffer** instance from the **OHNativeWindow** instance. 207e41f4b71Sopenharmony_ci 208e41f4b71Sopenharmony_ci ```c++ 209e41f4b71Sopenharmony_ci OHNativeWindowBuffer *buffer = nullptr; 210e41f4b71Sopenharmony_ci int fenceFd; 211e41f4b71Sopenharmony_ci // Obtain an OHNativeWindowBuffer instance by calling OH_NativeWindow_NativeWindowRequestBuffer. 212e41f4b71Sopenharmony_ci OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd); 213e41f4b71Sopenharmony_ci 214e41f4b71Sopenharmony_ci BufferHandle *handle = OH_NativeWindow_GetBufferHandleFromNative(buffer); 215e41f4b71Sopenharmony_ci ``` 216e41f4b71Sopenharmony_ci 217e41f4b71Sopenharmony_ci 2. Write the produced content to the **OHNativeWindowBuffer** instance. 218e41f4b71Sopenharmony_ci 219e41f4b71Sopenharmony_ci ```c++ 220e41f4b71Sopenharmony_ci // Use mmap() to obtain the memory virtual address of buffer handle. 221e41f4b71Sopenharmony_ci void *mappedAddr = mmap(handle->virAddr, handle->size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0); 222e41f4b71Sopenharmony_ci if (mappedAddr == MAP_FAILED) { 223e41f4b71Sopenharmony_ci // mmap failed 224e41f4b71Sopenharmony_ci } 225e41f4b71Sopenharmony_ci static uint32_t value = 0x00; 226e41f4b71Sopenharmony_ci value++; 227e41f4b71Sopenharmony_ci uint32_t *pixel = static_cast<uint32_t *>(mappedAddr); 228e41f4b71Sopenharmony_ci for (uint32_t x = 0; x < width; x++) { 229e41f4b71Sopenharmony_ci for (uint32_t y = 0; y < height; y++) { 230e41f4b71Sopenharmony_ci *pixel++ = value; 231e41f4b71Sopenharmony_ci } 232e41f4b71Sopenharmony_ci } 233e41f4b71Sopenharmony_ci // Unmap the memory when the memory is no longer required. 234e41f4b71Sopenharmony_ci int result = munmap(mappedAddr, handle->size); 235e41f4b71Sopenharmony_ci if (result == -1) { 236e41f4b71Sopenharmony_ci // munmap failed 237e41f4b71Sopenharmony_ci } 238e41f4b71Sopenharmony_ci ``` 239e41f4b71Sopenharmony_ci 240e41f4b71Sopenharmony_ci 3. Flush the **OHNativeWindowBuffer** to the **OHNativeWindow**. 241e41f4b71Sopenharmony_ci 242e41f4b71Sopenharmony_ci ```c++ 243e41f4b71Sopenharmony_ci // Set the refresh region. If Rect in Region is a null pointer or rectNumber is 0, all contents in the NativeWindowBuffer are changed. 244e41f4b71Sopenharmony_ci Region region{nullptr, 0}; 245e41f4b71Sopenharmony_ci // Flush the buffer to the consumer through OH_NativeWindow_NativeWindowFlushBuffer, for example, by displaying it on the screen. 246e41f4b71Sopenharmony_ci OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region); 247e41f4b71Sopenharmony_ci ``` 248e41f4b71Sopenharmony_ci 249e41f4b71Sopenharmony_ci 4. Destroy the **OHNativeWindow** instance when it is no longer needed. 250e41f4b71Sopenharmony_ci 251e41f4b71Sopenharmony_ci ```c++ 252e41f4b71Sopenharmony_ci OH_NativeWindow_DestroyNativeWindow(nativeWindow); 253e41f4b71Sopenharmony_ci ``` 254e41f4b71Sopenharmony_ci 255e41f4b71Sopenharmony_ci6. Update the content to the OpenGL texture. 256e41f4b71Sopenharmony_ci 257e41f4b71Sopenharmony_ci ```c++ 258e41f4b71Sopenharmony_ci // Update the content to the OpenGL texture. 259e41f4b71Sopenharmony_ci ret = OH_NativeImage_UpdateSurfaceImage(image); 260e41f4b71Sopenharmony_ci if (ret != 0) { 261e41f4b71Sopenharmony_ci std::cout << "OH_NativeImage_UpdateSurfaceImage failed" << std::endl; 262e41f4b71Sopenharmony_ci } 263e41f4b71Sopenharmony_ci // Obtain the timestamp and transformation matrix of the texture image that recently called the **OH_NativeImage_UpdateSurfaceImage** function. 264e41f4b71Sopenharmony_ci int64_t timeStamp = OH_NativeImage_GetTimestamp(image); 265e41f4b71Sopenharmony_ci float matrix[16]; 266e41f4b71Sopenharmony_ci ret = OH_NativeImage_GetTransformMatrix(image, matrix); 267e41f4b71Sopenharmony_ci if (ret != 0) { 268e41f4b71Sopenharmony_ci std::cout << "OH_NativeImage_GetTransformMatrix failed" << std::endl; 269e41f4b71Sopenharmony_ci } 270e41f4b71Sopenharmony_ci 271e41f4b71Sopenharmony_ci // Perform OpenGL post-processing on the texture, and then display the texture on the screen. 272e41f4b71Sopenharmony_ci EGLBoolean eglRet = eglSwapBuffers(eglDisplay_, eglSurface_); 273e41f4b71Sopenharmony_ci if (eglRet == EGL_FALSE) { 274e41f4b71Sopenharmony_ci std::cout << "eglSwapBuffers failed" << std::endl; 275e41f4b71Sopenharmony_ci } 276e41f4b71Sopenharmony_ci ``` 277e41f4b71Sopenharmony_ci 278e41f4b71Sopenharmony_ci7. Detach the **OH_NativeImage** from the current OpenGL texture and attach it to a new external texture. 279e41f4b71Sopenharmony_ci 280e41f4b71Sopenharmony_ci ```c++ 281e41f4b71Sopenharmony_ci // Detach an OH_NativeImage instance from the current OpenGL ES context. 282e41f4b71Sopenharmony_ci ret = OH_NativeImage_DetachContext(image); 283e41f4b71Sopenharmony_ci if (ret != 0) { 284e41f4b71Sopenharmony_ci std::cout << "OH_NativeImage_DetachContext failed" << std::endl; 285e41f4b71Sopenharmony_ci } 286e41f4b71Sopenharmony_ci // Attach an OH_NativeImage instance to the current OpenGL ES context. The OpenGL ES texture will be bound to an GL_TEXTURE_EXTERNAL_OES instance and updated through the OH_NativeImage instance. 287e41f4b71Sopenharmony_ci GLuint textureId2; 288e41f4b71Sopenharmony_ci glGenTextures(1, &textureId2); 289e41f4b71Sopenharmony_ci ret = OH_NativeImage_AttachContext(image, textureId2); 290e41f4b71Sopenharmony_ci ``` 291e41f4b71Sopenharmony_ci 292e41f4b71Sopenharmony_ci8. Destroy the **OH_NativeImage** instance when it is no longer needed. 293e41f4b71Sopenharmony_ci 294e41f4b71Sopenharmony_ci ```c++ 295e41f4b71Sopenharmony_ci // Destroy the OH_NativeImage instance. 296e41f4b71Sopenharmony_ci OH_NativeImage_Destroy(&image); 297e41f4b71Sopenharmony_ci ``` 298e41f4b71Sopenharmony_ci 299