D.1.2 ANDROID_image_native_buffer

The Android graphics stack builds on top of the Gralloc memory allocation library. Processes can share the handles that reference the Gralloc allocations. This interprocess shareability is key for supporting common use cases such as a camera driver sharing data with a rendering application.

SurfaceFlinger, the window composition service, can run on its own process and consume data from rendering applications because the Gralloc allocations are accessible across processes, making Android a very modular system.

A Gralloc allocation consists only of a chunk of memory and lacks any internal state describing what is stored on the buffer or any hint on how the buffer is used.

The next level of abstraction in the Android graphics stack is the user interface (UI) library, where an ANativeWindowBuffer struct is defined by putting together a Gralloc buffer with a description of its content and usage.

The ANativeBuffer struct is wrapped around a GraphicBuffer object that adds some convenient methods to the plain struct.

The application must create a Gralloc buffer by instantiating a GraphicBuffer, as in the following code example:

GraphicBuffer* graphicBuffer =
    new GraphicBuffer(
        width,
        height,
        (PixelFormat)pixel_format,
        GraphicBuffer::USAGE_HW_TEXTURE |
            GraphicBuffer::USAGE_HW_RENDER |
            GraphicBuffer::USAGE_SW_WRITE_RARELY |
            GraphicBuffer::USAGE_SW_READ_RARELY);

A pointer to a GraphicBuffer, the wrapper for an ANativeWindowBuffer, that is created in that way, can be used for specifying the image storage that an EGL image references to. In order to allow the creation of an EGL image out of an ANativeWindowBuffer pointer, Google requires that all Android vendors support the ANDROID_image_native_buffer extension, sitting on top of EGL_KHR_image_base. The ANDROID_image_native_buffer extension defines values for the eglCreateImageKHR parameters that must be supported on Android. When the target parameter is EGL_NATIVE_BUFFER_ANDROID then the buffer parameter can be an ANativeWindowBuffer pointer cast to EGLClientBuffer. To create an EGL image for the GraphicBuffer instance from the previous example, invoke eglCreateImageKHR as:

EGLImageKHR eglImage = eglCreateImageKHR(
                        display,
                        contenxt,
                        EGL_NATIVE_BUFFER_ANDROID,
                        graphicBuffer->getNativeBuffer(),
                        NULL);

The resulting EGL image can be used in OpenGL and OpenCL.

OpenCL supported formats

Shareable buffer formats that are supported for OpenCL.

The list of ANativeWindowBuffer formats that are supported for sharing data between OpenGL and OpenCL are as follows:

  • HAL_PIXEL_FORMAT_RGBA_8888
  • HAL_PIXEL_FORMAT_BGRA_8888
  • HAL_PIXEL_FORMAT_RGB_565
  • HAL_PIXEL_FORMAT_RGBX_8888
  • HAL_PIXEL_FORMAT_YV12

OpenCL image writing is only allowed for:

  • HAL_PIXEL_FORMAT_RGBA_8888
  • HAL_PIXEL_FORMAT_BGRA_8888
  • HAL_PIXEL_FORMAT_RGB_565
  • HAL_PIXEL_FORMAT_RGBX_8888

The result of writing to any format not listed here is undefined.

As a courtesy to OpenCL developers, the Mali™ OpenCL driver returns informative error codes on the clCreateFromEGLImageKHR calls:

CL_IMGE_FORMAT_NOT_SUPPORTED
If the format is not supported by the OpenCL driver.
CL_INVALID_OPERATION
If the format is known but the flags are invalid, because the CL_MEM_WRITE_ONLY or CL_MEM_READ_WRITE flags are specified for a format for which writing is not supported.
Non-ConfidentialPDF file icon PDF version101574_0301_00_en
Copyright © 2019 Arm Limited or its affiliates. All rights reserved.