android_util.cpp (14146B)
1 // 2 // Copyright 2018 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // android_util.cpp: Utilities for the using the Android platform 8 9 #include "common/android_util.h" 10 #include "common/debug.h" 11 12 #include <cstdint> 13 14 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26 15 # define ANGLE_AHARDWARE_BUFFER_SUPPORT 16 // NDK header file for access to Android Hardware Buffers 17 # include <android/hardware_buffer.h> 18 #endif 19 20 // Taken from cutils/native_handle.h: 21 // https://android.googlesource.com/platform/system/core/+/master/libcutils/include/cutils/native_handle.h 22 typedef struct native_handle 23 { 24 int version; /* sizeof(native_handle_t) */ 25 int numFds; /* number of file-descriptors at &data[0] */ 26 int numInts; /* number of ints at &data[numFds] */ 27 #if defined(__clang__) 28 # pragma clang diagnostic push 29 # pragma clang diagnostic ignored "-Wzero-length-array" 30 #elif defined(_MSC_VER) 31 # pragma warning(push) 32 # pragma warning(disable : 4200) 33 #endif 34 int data[0]; /* numFds + numInts ints */ 35 #if defined(__clang__) 36 # pragma clang diagnostic pop 37 #elif defined(_MSC_VER) 38 # pragma warning(pop) 39 #endif 40 } native_handle_t; 41 42 // Taken from nativebase/nativebase.h 43 // https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativebase/include/nativebase/nativebase.h 44 typedef const native_handle_t *buffer_handle_t; 45 46 typedef struct android_native_base_t 47 { 48 /* a magic value defined by the actual EGL native type */ 49 int magic; 50 /* the sizeof() of the actual EGL native type */ 51 int version; 52 void *reserved[4]; 53 /* reference-counting interface */ 54 void (*incRef)(struct android_native_base_t *base); 55 void (*decRef)(struct android_native_base_t *base); 56 } android_native_base_t; 57 58 typedef struct ANativeWindowBuffer 59 { 60 struct android_native_base_t common; 61 int width; 62 int height; 63 int stride; 64 int format; 65 int usage_deprecated; 66 uintptr_t layerCount; 67 void *reserved[1]; 68 const native_handle_t *handle; 69 uint64_t usage; 70 // we needed extra space for storing the 64-bits usage flags 71 // the number of slots to use from reserved_proc depends on the 72 // architecture. 73 void *reserved_proc[8 - (sizeof(uint64_t) / sizeof(void *))]; 74 } ANativeWindowBuffer_t; 75 76 // Taken from android/hardware_buffer.h 77 // https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativewindow/include/android/hardware_buffer.h 78 79 // AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM, 80 // AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM formats were deprecated and re-added explicitly. 81 82 // clang-format off 83 /** 84 * Buffer pixel formats. 85 */ 86 enum { 87 88 #ifndef ANGLE_AHARDWARE_BUFFER_SUPPORT 89 /** 90 * Corresponding formats: 91 * Vulkan: VK_FORMAT_R8G8B8A8_UNORM 92 * OpenGL ES: GL_RGBA8 93 */ 94 AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1, 95 96 /** 97 * 32 bits per pixel, 8 bits per channel format where alpha values are 98 * ignored (always opaque). 99 * Corresponding formats: 100 * Vulkan: VK_FORMAT_R8G8B8A8_UNORM 101 * OpenGL ES: GL_RGB8 102 */ 103 AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM = 2, 104 105 /** 106 * Corresponding formats: 107 * Vulkan: VK_FORMAT_R8G8B8_UNORM 108 * OpenGL ES: GL_RGB8 109 */ 110 AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM = 3, 111 112 /** 113 * Corresponding formats: 114 * Vulkan: VK_FORMAT_R5G6B5_UNORM_PACK16 115 * OpenGL ES: GL_RGB565 116 */ 117 AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4, 118 #endif // ANGLE_AHARDWARE_BUFFER_SUPPORT 119 120 AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM = 5, 121 AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM = 6, 122 AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM = 7, 123 124 #ifndef ANGLE_AHARDWARE_BUFFER_SUPPORT 125 /** 126 * Corresponding formats: 127 * Vulkan: VK_FORMAT_R16G16B16A16_SFLOAT 128 * OpenGL ES: GL_RGBA16F 129 */ 130 AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT = 0x16, 131 132 /** 133 * Corresponding formats: 134 * Vulkan: VK_FORMAT_A2B10G10R10_UNORM_PACK32 135 * OpenGL ES: GL_RGB10_A2 136 */ 137 AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b, 138 139 /** 140 * An opaque binary blob format that must have height 1, with width equal to 141 * the buffer size in bytes. 142 */ 143 AHARDWAREBUFFER_FORMAT_BLOB = 0x21, 144 145 /** 146 * Corresponding formats: 147 * Vulkan: VK_FORMAT_D16_UNORM 148 * OpenGL ES: GL_DEPTH_COMPONENT16 149 */ 150 AHARDWAREBUFFER_FORMAT_D16_UNORM = 0x30, 151 152 /** 153 * Corresponding formats: 154 * Vulkan: VK_FORMAT_X8_D24_UNORM_PACK32 155 * OpenGL ES: GL_DEPTH_COMPONENT24 156 */ 157 AHARDWAREBUFFER_FORMAT_D24_UNORM = 0x31, 158 159 /** 160 * Corresponding formats: 161 * Vulkan: VK_FORMAT_D24_UNORM_S8_UINT 162 * OpenGL ES: GL_DEPTH24_STENCIL8 163 */ 164 AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT = 0x32, 165 166 /** 167 * Corresponding formats: 168 * Vulkan: VK_FORMAT_D32_SFLOAT 169 * OpenGL ES: GL_DEPTH_COMPONENT32F 170 */ 171 AHARDWAREBUFFER_FORMAT_D32_FLOAT = 0x33, 172 173 /** 174 * Corresponding formats: 175 * Vulkan: VK_FORMAT_D32_SFLOAT_S8_UINT 176 * OpenGL ES: GL_DEPTH32F_STENCIL8 177 */ 178 AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT = 0x34, 179 180 /** 181 * Corresponding formats: 182 * Vulkan: VK_FORMAT_S8_UINT 183 * OpenGL ES: GL_STENCIL_INDEX8 184 */ 185 AHARDWAREBUFFER_FORMAT_S8_UINT = 0x35, 186 187 /** 188 * YUV 420 888 format. 189 * Must have an even width and height. Can be accessed in OpenGL 190 * shaders through an external sampler. Does not support mip-maps 191 * cube-maps or multi-layered textures. 192 */ 193 AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23, 194 195 #endif // ANGLE_AHARDWARE_BUFFER_SUPPORT 196 197 AHARDWAREBUFFER_FORMAT_YV12 = 0x32315659, 198 AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED = 0x22, 199 }; 200 // clang-format on 201 202 namespace 203 { 204 205 // In the Android system: 206 // - AHardwareBuffer is essentially a typedef of GraphicBuffer. Conversion functions simply 207 // reinterpret_cast. 208 // - GraphicBuffer inherits from two base classes, ANativeWindowBuffer and RefBase. 209 // 210 // GraphicBuffer implements a getter for ANativeWindowBuffer (getNativeBuffer) by static_casting 211 // itself to its base class ANativeWindowBuffer. The offset of the ANativeWindowBuffer pointer 212 // from the GraphicBuffer pointer is 16 bytes. This is likely due to two pointers: The vtable of 213 // GraphicBuffer and the one pointer member of the RefBase class. 214 // 215 // This is not future proof at all. We need to look into getting utilities added to Android to 216 // perform this cast for us. 217 constexpr int kAHardwareBufferToANativeWindowBufferOffset = static_cast<int>(sizeof(void *)) * 2; 218 219 template <typename T1, typename T2> 220 T1 *OffsetPointer(T2 *ptr, int bytes) 221 { 222 return reinterpret_cast<T1 *>(reinterpret_cast<intptr_t>(ptr) + bytes); 223 } 224 225 GLenum GetPixelFormatInfo(int pixelFormat, bool *isYUV) 226 { 227 *isYUV = false; 228 switch (pixelFormat) 229 { 230 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM: 231 return GL_RGBA8; 232 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM: 233 return GL_RGB8; 234 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM: 235 return GL_RGB8; 236 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM: 237 return GL_RGB565; 238 case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM: 239 return GL_BGRA8_EXT; 240 case AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM: 241 return GL_RGB5_A1; 242 case AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM: 243 return GL_RGBA4; 244 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT: 245 return GL_RGBA16F; 246 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM: 247 return GL_RGB10_A2; 248 case AHARDWAREBUFFER_FORMAT_BLOB: 249 return GL_NONE; 250 case AHARDWAREBUFFER_FORMAT_D16_UNORM: 251 return GL_DEPTH_COMPONENT16; 252 case AHARDWAREBUFFER_FORMAT_D24_UNORM: 253 return GL_DEPTH_COMPONENT24; 254 case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT: 255 return GL_DEPTH24_STENCIL8; 256 case AHARDWAREBUFFER_FORMAT_D32_FLOAT: 257 return GL_DEPTH_COMPONENT32F; 258 case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT: 259 return GL_DEPTH32F_STENCIL8; 260 case AHARDWAREBUFFER_FORMAT_S8_UINT: 261 return GL_STENCIL_INDEX8; 262 case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: 263 case AHARDWAREBUFFER_FORMAT_YV12: 264 case AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED: 265 *isYUV = true; 266 return GL_RGB8; 267 default: 268 // Treat unknown formats as RGB. They are vendor-specific YUV formats that would sample 269 // as RGB. 270 *isYUV = true; 271 return GL_RGB8; 272 } 273 } 274 275 } // anonymous namespace 276 277 namespace angle 278 { 279 280 namespace android 281 { 282 283 ANativeWindowBuffer *ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer) 284 { 285 return reinterpret_cast<ANativeWindowBuffer *>(clientBuffer); 286 } 287 288 uint64_t GetAHBUsage(int eglNativeBufferUsage) 289 { 290 uint64_t ahbUsage = 0; 291 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT) 292 if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) 293 { 294 ahbUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT; 295 } 296 if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) 297 { 298 ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER; 299 } 300 if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) 301 { 302 ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; 303 } 304 #endif // ANGLE_AHARDWARE_BUFFER_SUPPORT 305 return ahbUsage; 306 } 307 308 EGLClientBuffer CreateEGLClientBufferFromAHardwareBuffer(int width, 309 int height, 310 int depth, 311 int androidFormat, 312 int usage) 313 { 314 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT) 315 316 // The height and width are number of pixels of size format 317 AHardwareBuffer_Desc aHardwareBufferDescription = {}; 318 aHardwareBufferDescription.width = static_cast<uint32_t>(width); 319 aHardwareBufferDescription.height = static_cast<uint32_t>(height); 320 aHardwareBufferDescription.layers = static_cast<uint32_t>(depth); 321 aHardwareBufferDescription.format = androidFormat; 322 aHardwareBufferDescription.usage = GetAHBUsage(usage); 323 324 // Allocate memory from Android Hardware Buffer 325 AHardwareBuffer *aHardwareBuffer = nullptr; 326 int res = AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer); 327 if (res != 0) 328 { 329 return nullptr; 330 } 331 332 return AHardwareBufferToClientBuffer(aHardwareBuffer); 333 #else 334 return nullptr; 335 #endif // ANGLE_AHARDWARE_BUFFER_SUPPORT 336 } 337 338 void GetANativeWindowBufferProperties(const ANativeWindowBuffer *buffer, 339 int *width, 340 int *height, 341 int *depth, 342 int *pixelFormat, 343 uint64_t *usage) 344 { 345 *width = buffer->width; 346 *height = buffer->height; 347 *depth = static_cast<int>(buffer->layerCount); 348 *height = buffer->height; 349 *pixelFormat = buffer->format; 350 *usage = buffer->usage; 351 } 352 353 GLenum NativePixelFormatToGLInternalFormat(int pixelFormat) 354 { 355 bool isYuv = false; 356 return GetPixelFormatInfo(pixelFormat, &isYuv); 357 } 358 359 int GLInternalFormatToNativePixelFormat(GLenum internalFormat) 360 { 361 switch (internalFormat) 362 { 363 case GL_RGBA8: 364 return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; 365 case GL_RGB8: 366 return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM; 367 case GL_RGB565: 368 return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM; 369 case GL_BGRA8_EXT: 370 return AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM; 371 case GL_RGB5_A1: 372 return AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM; 373 case GL_RGBA4: 374 return AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM; 375 case GL_RGBA16F: 376 return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT; 377 case GL_RGB10_A2: 378 return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM; 379 case GL_NONE: 380 return AHARDWAREBUFFER_FORMAT_BLOB; 381 case GL_DEPTH_COMPONENT16: 382 return AHARDWAREBUFFER_FORMAT_D16_UNORM; 383 case GL_DEPTH_COMPONENT24: 384 return AHARDWAREBUFFER_FORMAT_D24_UNORM; 385 case GL_DEPTH24_STENCIL8: 386 return AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT; 387 case GL_DEPTH_COMPONENT32F: 388 return AHARDWAREBUFFER_FORMAT_D32_FLOAT; 389 case GL_DEPTH32F_STENCIL8: 390 return AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT; 391 case GL_STENCIL_INDEX8: 392 return AHARDWAREBUFFER_FORMAT_S8_UINT; 393 default: 394 WARN() << "Unknown internalFormat: " << internalFormat << ". Treating as 0"; 395 return 0; 396 } 397 } 398 399 bool NativePixelFormatIsYUV(int pixelFormat) 400 { 401 bool isYuv = false; 402 GetPixelFormatInfo(pixelFormat, &isYuv); 403 return isYuv; 404 } 405 406 AHardwareBuffer *ANativeWindowBufferToAHardwareBuffer(ANativeWindowBuffer *windowBuffer) 407 { 408 return OffsetPointer<AHardwareBuffer>(windowBuffer, 409 -kAHardwareBufferToANativeWindowBufferOffset); 410 } 411 412 EGLClientBuffer AHardwareBufferToClientBuffer(const AHardwareBuffer *hardwareBuffer) 413 { 414 return OffsetPointer<EGLClientBuffer>(hardwareBuffer, 415 kAHardwareBufferToANativeWindowBufferOffset); 416 } 417 418 AHardwareBuffer *ClientBufferToAHardwareBuffer(EGLClientBuffer clientBuffer) 419 { 420 return OffsetPointer<AHardwareBuffer>(clientBuffer, 421 -kAHardwareBufferToANativeWindowBufferOffset); 422 } 423 } // namespace android 424 } // namespace angle