Loading libs/nativewindow/AHardwareBuffer.cpp +98 −37 Original line number Diff line number Diff line Loading @@ -41,32 +41,10 @@ using namespace android; // ---------------------------------------------------------------------------- int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) { if (!outBuffer || !desc) return BAD_VALUE; if (!AHardwareBuffer_isValidPixelFormat(desc->format)) { ALOGE("Invalid AHardwareBuffer pixel format %u (%#x))", desc->format, desc->format); return BAD_VALUE; } if (!outBuffer || !desc) return BAD_VALUE; if (!AHardwareBuffer_isValidDescription(desc, /*log=*/true)) return BAD_VALUE; int format = AHardwareBuffer_convertToPixelFormat(desc->format); if (desc->rfu0 != 0 || desc->rfu1 != 0) { ALOGE("AHardwareBuffer_Desc::rfu fields must be 0"); return BAD_VALUE; } if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1) { ALOGE("Height must be 1 when using the AHARDWAREBUFFER_FORMAT_BLOB format"); return BAD_VALUE; } if ((desc->usage & (AHARDWAREBUFFER_USAGE_CPU_READ_MASK | AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) && (desc->usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT)) { ALOGE("AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT requires AHARDWAREBUFFER_USAGE_CPU_READ_NEVER " "and AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER"); return BAD_VALUE; } uint64_t usage = AHardwareBuffer_convertToGrallocUsageBits(desc->usage); sp<GraphicBuffer> gbuffer(new GraphicBuffer( desc->width, desc->height, format, desc->layers, usage, Loading Loading @@ -127,14 +105,21 @@ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, } usage = AHardwareBuffer_convertToGrallocUsageBits(usage); GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer); GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer); if (gbuffer->getLayerCount() > 1) { ALOGE("Buffer with multiple layers passed to AHardwareBuffer_lock; " "only buffers with one layer are allowed"); return INVALID_OPERATION; } Rect bounds; if (!rect) { bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight())); bounds.set(Rect(gbuffer->getWidth(), gbuffer->getHeight())); } else { bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom)); } return gBuffer->lockAsync(usage, usage, bounds, outVirtualAddress, fence); return gbuffer->lockAsync(usage, usage, bounds, outVirtualAddress, fence); } int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) { Loading Loading @@ -274,6 +259,25 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out return NO_ERROR; } int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) { if (!desc) return 0; if (!AHardwareBuffer_isValidDescription(desc, /*log=*/false)) return 0; // Make a trial allocation. // TODO(b/115660272): add implementation that uses a HAL query. AHardwareBuffer_Desc trialDesc = *desc; trialDesc.width = 4; trialDesc.height = desc->format == AHARDWAREBUFFER_FORMAT_BLOB ? 1 : 4; trialDesc.layers = desc->layers == 1 ? 1 : 2; AHardwareBuffer* trialBuffer = nullptr; int result = AHardwareBuffer_allocate(&trialDesc, &trialBuffer); if (result == NO_ERROR) { AHardwareBuffer_release(trialBuffer); return 1; } return 0; } // ---------------------------------------------------------------------------- // VNDK functions Loading Loading @@ -322,14 +326,71 @@ int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* desc, namespace android { // A 1:1 mapping of AHardwaqreBuffer bitmasks to gralloc1 bitmasks. struct UsageMaskMapping { uint64_t hardwareBufferMask; uint64_t grallocMask; }; bool AHardwareBuffer_isValidDescription(const AHardwareBuffer_Desc* desc, bool log) { if (desc->width == 0 || desc->height == 0 || desc->layers == 0) { ALOGE_IF(log, "Width, height and layers must all be nonzero"); return false; } static inline bool containsBits(uint64_t mask, uint64_t bitsToCheck) { return (mask & bitsToCheck) == bitsToCheck && bitsToCheck; if (!AHardwareBuffer_isValidPixelFormat(desc->format)) { ALOGE_IF(log, "Invalid AHardwareBuffer pixel format %u (%#x))", desc->format, desc->format); return false; } if (desc->rfu0 != 0 || desc->rfu1 != 0) { ALOGE_IF(log, "AHardwareBuffer_Desc::rfu fields must be 0"); return false; } if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB) { if (desc->height != 1 || desc->layers != 1) { ALOGE_IF(log, "Height and layers must be 1 for AHARDWAREBUFFER_FORMAT_BLOB"); return false; } const uint64_t blobInvalidGpuMask = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER | AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE | AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; if (desc->usage & blobInvalidGpuMask) { ALOGE_IF(log, "Invalid GPU usage flag for AHARDWAREBUFFER_FORMAT_BLOB; " "only AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER is allowed"); return false; } if (desc->usage & AHARDWAREBUFFER_USAGE_VIDEO_ENCODE) { ALOGE_IF(log, "AHARDWAREBUFFER_FORMAT_BLOB cannot be encoded as video"); return false; } } else { if (desc->usage & AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA) { ALOGE_IF(log, "AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA requires AHARDWAREBUFFER_FORMAT_BLOB"); return false; } if (desc->usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) { ALOGE_IF(log, "AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER requires AHARDWAREBUFFER_FORMAT_BLOB"); return false; } } if ((desc->usage & (AHARDWAREBUFFER_USAGE_CPU_READ_MASK | AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) && (desc->usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT)) { ALOGE_IF(log, "AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT requires AHARDWAREBUFFER_USAGE_CPU_READ_NEVER " "and AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER"); return false; } if (desc->usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) { if (desc->width != desc->height) { ALOGE_IF(log, "Cube maps must be square"); return false; } if (desc->layers % 6 != 0) { ALOGE_IF(log, "Cube map layers must be a multiple of 6"); return false; } } return true; } bool AHardwareBuffer_isValidPixelFormat(uint32_t format) { Loading Loading @@ -445,7 +506,7 @@ uint64_t AHardwareBuffer_convertToGrallocUsageBits(uint64_t usage) { "gralloc and AHardwareBuffer flags don't match"); static_assert(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE == (uint64_t)BufferUsage::GPU_TEXTURE, "gralloc and AHardwareBuffer flags don't match"); static_assert(AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT == (uint64_t)BufferUsage::GPU_RENDER_TARGET, static_assert(AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER == (uint64_t)BufferUsage::GPU_RENDER_TARGET, "gralloc and AHardwareBuffer flags don't match"); static_assert(AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT == (uint64_t)BufferUsage::PROTECTED, "gralloc and AHardwareBuffer flags don't match"); Loading libs/nativewindow/include-private/private/android/AHardwareBufferHelpers.h +5 −0 Original line number Diff line number Diff line Loading @@ -28,10 +28,15 @@ #include <stdint.h> struct AHardwareBuffer; struct AHardwareBuffer_Desc; struct ANativeWindowBuffer; namespace android { // Validates whether the passed description does not have conflicting // parameters. Note: this does not verify any platform-specific contraints. bool AHardwareBuffer_isValidDescription(const AHardwareBuffer_Desc* desc, bool log); // whether this AHardwareBuffer format is valid bool AHardwareBuffer_isValidPixelFormat(uint32_t ahardwarebuffer_format); Loading libs/nativewindow/include/android/hardware_buffer.h +122 −53 Original line number Diff line number Diff line Loading @@ -102,8 +102,10 @@ enum AHardwareBuffer_Format { AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b, /** * An opaque binary blob format that must have height 1, with width equal to * the buffer size in bytes. * Opaque binary blob format. * Must have height 1 and one layer, with width equal to the buffer * size in bytes. Corresponds to Vulkan buffers and OpenGL buffer * objects. Can be bound to the latter using GL_EXT_external_buffer. */ AHARDWAREBUFFER_FORMAT_BLOB = 0x21, Loading Loading @@ -195,20 +197,25 @@ enum AHardwareBuffer_UsageFlags { /// The buffer will be written to by the GPU as a framebuffer attachment. AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER = 1UL << 9, /** * The buffer will be written to by the GPU as a framebuffer attachment. * Note that the name of this flag is somewhat misleading: it does not imply * that the buffer contains a color format. A buffer with depth or stencil * format that will be used as a framebuffer attachment should also have * this flag. * The buffer will be written to by the GPU as a framebuffer * attachment. * * Note that the name of this flag is somewhat misleading: it does * not imply that the buffer contains a color format. A buffer with * depth or stencil format that will be used as a framebuffer * attachment should also have this flag. Use the equivalent flag * AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER to avoid this confusion. */ AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, /** * The buffer is protected from direct CPU access or being read by non-secure * hardware, such as video encoders. This flag is incompatible with CPU * read and write flags. It is mainly used when handling DRM video. * Refer to the EGL extension EGL_EXT_protected_content and GL extension * EXT_protected_textures for more information on how these buffers are expected * to behave. * The buffer is protected from direct CPU access or being read by * non-secure hardware, such as video encoders. * * This flag is incompatible with CPU read and write flags. It is * mainly used when handling DRM video. Refer to the EGL extension * EGL_EXT_protected_content and GL extension * GL_EXT_protected_textures for more information on how these * buffers are expected to behave. */ AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14, /// The buffer will be read by a hardware video encoder. Loading @@ -225,11 +232,17 @@ enum AHardwareBuffer_UsageFlags { AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24, /** * The buffer will be used as a cube map texture. * When this flag is present, the buffer must have a layer count that is * a multiple of 6. * When this flag is present, the buffer must have a layer count * that is a multiple of 6. Note that buffers with this flag must be * bound to OpenGL textures using the extension * GL_EXT_EGL_image_storage instead of GL_KHR_EGL_image. */ AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP = 1UL << 25, /// The buffer contains a complete mipmap hierarchy. /** * The buffer contains a complete mipmap hierarchy. * Note that buffers with this flag must be bound to OpenGL textures using * the extension GL_EXT_EGL_image_storage instead of GL_KHR_EGL_image. */ AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE = 1UL << 26, AHARDWAREBUFFER_USAGE_VENDOR_0 = 1ULL << 28, Loading @@ -255,13 +268,21 @@ enum AHardwareBuffer_UsageFlags { }; /** * Buffer description. Used for allocating new buffers and querying parameters * of existing ones. * Buffer description. Used for allocating new buffers and querying * parameters of existing ones. */ typedef struct AHardwareBuffer_Desc { uint32_t width; ///< Width in pixels. uint32_t height; ///< Height in pixels. uint32_t layers; ///< Number of images in an image array. /** * Number of images in an image array. AHardwareBuffers with one * layer correspond to regular 2D textures. AHardwareBuffers with * more than layer correspond to texture arrays. If the layer count * is a multiple of 6 and the usage flag * AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP is present, the buffer is * a cube map or a cube map array. */ uint32_t layers; uint32_t format; ///< One of AHardwareBuffer_Format. uint64_t usage; ///< Combination of AHardwareBuffer_UsageFlags. uint32_t stride; ///< Row stride in pixels, ignored for AHardwareBuffer_allocate() Loading Loading @@ -290,8 +311,10 @@ typedef struct AHardwareBuffer AHardwareBuffer; int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) __INTRODUCED_IN(26); /** * Acquire a reference on the given AHardwareBuffer object. This prevents the * object from being deleted until the last reference is removed. * Acquire a reference on the given AHardwareBuffer object. * * This prevents the object from being deleted until the last reference * is removed. */ void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26); Loading @@ -309,50 +332,73 @@ void AHardwareBuffer_describe(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26); /** * Lock the AHardwareBuffer for reading or writing, depending on the usage flags * passed. This call may block if the hardware needs to finish rendering or if * CPU caches need to be synchronized, or possibly for other implementation- * specific reasons. If fence is not negative, then it specifies a fence file * descriptor that will be signaled when the buffer is locked, otherwise the * caller will block until the buffer is available. * Lock the AHardwareBuffer for direct CPU access. * * If \a rect is not NULL, the caller promises to modify only data in the area * specified by rect. If rect is NULL, the caller may modify the contents of the * entire buffer. * This function can lock the buffer for either reading or writing. * It may block if the hardware needs to finish rendering, if CPU caches * need to be synchronized, or possibly for other implementation- * specific reasons. * * The content of the buffer outside of the specified rect is NOT modified * by this call. * The passed AHardwareBuffer must have one layer, otherwise the call * will fail. * * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*. If set, * then outVirtualAddress is filled with the address of the buffer in virtual * memory. * If \a fence is not negative, it specifies a fence file descriptor on * which to wait before locking the buffer. If it's negative, the caller * is responsible for ensuring that writes to the buffer have completed * before calling this function. Using this parameter is more efficient * than waiting on the fence and then calling this function. * * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*. * If set, then outVirtualAddress is filled with the address of the * buffer in virtual memory. The flags must also be compatible with * usage flags specified at buffer creation: if a read flag is passed, * the buffer must have been created with * AHARDWAREBUFFER_USAGE_CPU_READ_RARELY or * AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN. If a write flag is passed, it * must have been created with AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY or * AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN. * * THREADING CONSIDERATIONS: * If \a rect is not NULL, the caller promises to modify only data in * the area specified by rect. If rect is NULL, the caller may modify * the contents of the entire buffer. The content of the buffer outside * of the specified rect is NOT modified by this call. * * It is legal for several different threads to lock a buffer for read access; * none of the threads are blocked. * It is legal for several different threads to lock a buffer for read * access; none of the threads are blocked. * * Locking a buffer simultaneously for write or read/write is undefined, but * will neither terminate the process nor block the caller; AHardwareBuffer_lock * may return an error or leave the buffer's content into an indeterminate * state. * Locking a buffer simultaneously for write or read/write is undefined, * but will neither terminate the process nor block the caller. * AHardwareBuffer_lock may return an error or leave the buffer's * content in an indeterminate state. * * If the buffer has AHARDWAREBUFFER_FORMAT_BLOB, it is legal lock it * for reading and writing in multiple threads and/or processes * simultaneously, and the contents of the buffer behave like shared * memory. * * \return 0 on success, -EINVAL if \a buffer is NULL or if the usage * flags are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or an error * number of the lock fails for any reason. * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer * has more than one layer. Error number if the lock fails for any other * reason. */ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26); /** * Unlock the AHardwareBuffer; must be called after all changes to the buffer * are completed by the caller. If fence is not NULL then it will be set to a * file descriptor that is signaled when all pending work on the buffer is * completed. The caller is responsible for closing the fence when it is no * longer needed. * Unlock the AHardwareBuffer from direct CPU access. * * \return 0 on success, -EINVAL if \a buffer is NULL, or an error * number if the unlock fails for any reason. * Must be called after all changes to the buffer are completed by the * caller. If \a fence is NULL, the function will block until all work * is completed. Otherwise, \a fence will be set either to a valid file * descriptor or to -1. The file descriptor will become signaled once * the unlocking is complete and buffer contents are updated. * The caller is responsible for closing the file descriptor once it's * no longer needed. The value -1 indicates that unlocking has already * completed before the function returned and no further operations are * necessary. * * \return 0 on success. -EINVAL if \a buffer is NULL. Error number if * the unlock fails for any reason. */ int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED_IN(26); Loading @@ -365,7 +411,7 @@ int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd) __INTRODUCED_IN(26); /** * Receive the AHardwareBuffer from an AF_UNIX socket. * Receive an AHardwareBuffer from an AF_UNIX socket. * * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error * number if the operation fails for any reason. Loading @@ -374,6 +420,29 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out #endif // __ANDROID_API__ >= 26 #if __ANDROID_API__ >= 29 /** * Test whether the given format and usage flag combination is * allocatable. * * If this function returns true, it means that a buffer with the given * description can be allocated on this implementation, unless resource * exhaustion occurs. If this function returns false, it means that the * allocation of the given description will never succeed. * * The return value of this function may depend on all fields in the * description, except stride, which is always ignored. For example, * some implementations have implementation-defined limits on texture * size and layer count. * * \return 1 if the format and usage flag combination is allocatable, * 0 otherwise. */ int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) __INTRODUCED_IN(29); #endif // __ANDROID_API__ >= 29 __END_DECLS #endif // ANDROID_HARDWARE_BUFFER_H Loading libs/nativewindow/libnativewindow.map.txt +1 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ LIBNATIVEWINDOW { AHardwareBuffer_createFromHandle; # vndk AHardwareBuffer_describe; AHardwareBuffer_getNativeHandle; # vndk AHardwareBuffer_isSupported; # introduced=29 AHardwareBuffer_lock; AHardwareBuffer_recvHandleFromUnixSocket; AHardwareBuffer_release; Loading Loading
libs/nativewindow/AHardwareBuffer.cpp +98 −37 Original line number Diff line number Diff line Loading @@ -41,32 +41,10 @@ using namespace android; // ---------------------------------------------------------------------------- int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) { if (!outBuffer || !desc) return BAD_VALUE; if (!AHardwareBuffer_isValidPixelFormat(desc->format)) { ALOGE("Invalid AHardwareBuffer pixel format %u (%#x))", desc->format, desc->format); return BAD_VALUE; } if (!outBuffer || !desc) return BAD_VALUE; if (!AHardwareBuffer_isValidDescription(desc, /*log=*/true)) return BAD_VALUE; int format = AHardwareBuffer_convertToPixelFormat(desc->format); if (desc->rfu0 != 0 || desc->rfu1 != 0) { ALOGE("AHardwareBuffer_Desc::rfu fields must be 0"); return BAD_VALUE; } if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1) { ALOGE("Height must be 1 when using the AHARDWAREBUFFER_FORMAT_BLOB format"); return BAD_VALUE; } if ((desc->usage & (AHARDWAREBUFFER_USAGE_CPU_READ_MASK | AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) && (desc->usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT)) { ALOGE("AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT requires AHARDWAREBUFFER_USAGE_CPU_READ_NEVER " "and AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER"); return BAD_VALUE; } uint64_t usage = AHardwareBuffer_convertToGrallocUsageBits(desc->usage); sp<GraphicBuffer> gbuffer(new GraphicBuffer( desc->width, desc->height, format, desc->layers, usage, Loading Loading @@ -127,14 +105,21 @@ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, } usage = AHardwareBuffer_convertToGrallocUsageBits(usage); GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer); GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer); if (gbuffer->getLayerCount() > 1) { ALOGE("Buffer with multiple layers passed to AHardwareBuffer_lock; " "only buffers with one layer are allowed"); return INVALID_OPERATION; } Rect bounds; if (!rect) { bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight())); bounds.set(Rect(gbuffer->getWidth(), gbuffer->getHeight())); } else { bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom)); } return gBuffer->lockAsync(usage, usage, bounds, outVirtualAddress, fence); return gbuffer->lockAsync(usage, usage, bounds, outVirtualAddress, fence); } int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) { Loading Loading @@ -274,6 +259,25 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out return NO_ERROR; } int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) { if (!desc) return 0; if (!AHardwareBuffer_isValidDescription(desc, /*log=*/false)) return 0; // Make a trial allocation. // TODO(b/115660272): add implementation that uses a HAL query. AHardwareBuffer_Desc trialDesc = *desc; trialDesc.width = 4; trialDesc.height = desc->format == AHARDWAREBUFFER_FORMAT_BLOB ? 1 : 4; trialDesc.layers = desc->layers == 1 ? 1 : 2; AHardwareBuffer* trialBuffer = nullptr; int result = AHardwareBuffer_allocate(&trialDesc, &trialBuffer); if (result == NO_ERROR) { AHardwareBuffer_release(trialBuffer); return 1; } return 0; } // ---------------------------------------------------------------------------- // VNDK functions Loading Loading @@ -322,14 +326,71 @@ int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* desc, namespace android { // A 1:1 mapping of AHardwaqreBuffer bitmasks to gralloc1 bitmasks. struct UsageMaskMapping { uint64_t hardwareBufferMask; uint64_t grallocMask; }; bool AHardwareBuffer_isValidDescription(const AHardwareBuffer_Desc* desc, bool log) { if (desc->width == 0 || desc->height == 0 || desc->layers == 0) { ALOGE_IF(log, "Width, height and layers must all be nonzero"); return false; } static inline bool containsBits(uint64_t mask, uint64_t bitsToCheck) { return (mask & bitsToCheck) == bitsToCheck && bitsToCheck; if (!AHardwareBuffer_isValidPixelFormat(desc->format)) { ALOGE_IF(log, "Invalid AHardwareBuffer pixel format %u (%#x))", desc->format, desc->format); return false; } if (desc->rfu0 != 0 || desc->rfu1 != 0) { ALOGE_IF(log, "AHardwareBuffer_Desc::rfu fields must be 0"); return false; } if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB) { if (desc->height != 1 || desc->layers != 1) { ALOGE_IF(log, "Height and layers must be 1 for AHARDWAREBUFFER_FORMAT_BLOB"); return false; } const uint64_t blobInvalidGpuMask = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER | AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE | AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; if (desc->usage & blobInvalidGpuMask) { ALOGE_IF(log, "Invalid GPU usage flag for AHARDWAREBUFFER_FORMAT_BLOB; " "only AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER is allowed"); return false; } if (desc->usage & AHARDWAREBUFFER_USAGE_VIDEO_ENCODE) { ALOGE_IF(log, "AHARDWAREBUFFER_FORMAT_BLOB cannot be encoded as video"); return false; } } else { if (desc->usage & AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA) { ALOGE_IF(log, "AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA requires AHARDWAREBUFFER_FORMAT_BLOB"); return false; } if (desc->usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) { ALOGE_IF(log, "AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER requires AHARDWAREBUFFER_FORMAT_BLOB"); return false; } } if ((desc->usage & (AHARDWAREBUFFER_USAGE_CPU_READ_MASK | AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) && (desc->usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT)) { ALOGE_IF(log, "AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT requires AHARDWAREBUFFER_USAGE_CPU_READ_NEVER " "and AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER"); return false; } if (desc->usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) { if (desc->width != desc->height) { ALOGE_IF(log, "Cube maps must be square"); return false; } if (desc->layers % 6 != 0) { ALOGE_IF(log, "Cube map layers must be a multiple of 6"); return false; } } return true; } bool AHardwareBuffer_isValidPixelFormat(uint32_t format) { Loading Loading @@ -445,7 +506,7 @@ uint64_t AHardwareBuffer_convertToGrallocUsageBits(uint64_t usage) { "gralloc and AHardwareBuffer flags don't match"); static_assert(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE == (uint64_t)BufferUsage::GPU_TEXTURE, "gralloc and AHardwareBuffer flags don't match"); static_assert(AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT == (uint64_t)BufferUsage::GPU_RENDER_TARGET, static_assert(AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER == (uint64_t)BufferUsage::GPU_RENDER_TARGET, "gralloc and AHardwareBuffer flags don't match"); static_assert(AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT == (uint64_t)BufferUsage::PROTECTED, "gralloc and AHardwareBuffer flags don't match"); Loading
libs/nativewindow/include-private/private/android/AHardwareBufferHelpers.h +5 −0 Original line number Diff line number Diff line Loading @@ -28,10 +28,15 @@ #include <stdint.h> struct AHardwareBuffer; struct AHardwareBuffer_Desc; struct ANativeWindowBuffer; namespace android { // Validates whether the passed description does not have conflicting // parameters. Note: this does not verify any platform-specific contraints. bool AHardwareBuffer_isValidDescription(const AHardwareBuffer_Desc* desc, bool log); // whether this AHardwareBuffer format is valid bool AHardwareBuffer_isValidPixelFormat(uint32_t ahardwarebuffer_format); Loading
libs/nativewindow/include/android/hardware_buffer.h +122 −53 Original line number Diff line number Diff line Loading @@ -102,8 +102,10 @@ enum AHardwareBuffer_Format { AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b, /** * An opaque binary blob format that must have height 1, with width equal to * the buffer size in bytes. * Opaque binary blob format. * Must have height 1 and one layer, with width equal to the buffer * size in bytes. Corresponds to Vulkan buffers and OpenGL buffer * objects. Can be bound to the latter using GL_EXT_external_buffer. */ AHARDWAREBUFFER_FORMAT_BLOB = 0x21, Loading Loading @@ -195,20 +197,25 @@ enum AHardwareBuffer_UsageFlags { /// The buffer will be written to by the GPU as a framebuffer attachment. AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER = 1UL << 9, /** * The buffer will be written to by the GPU as a framebuffer attachment. * Note that the name of this flag is somewhat misleading: it does not imply * that the buffer contains a color format. A buffer with depth or stencil * format that will be used as a framebuffer attachment should also have * this flag. * The buffer will be written to by the GPU as a framebuffer * attachment. * * Note that the name of this flag is somewhat misleading: it does * not imply that the buffer contains a color format. A buffer with * depth or stencil format that will be used as a framebuffer * attachment should also have this flag. Use the equivalent flag * AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER to avoid this confusion. */ AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, /** * The buffer is protected from direct CPU access or being read by non-secure * hardware, such as video encoders. This flag is incompatible with CPU * read and write flags. It is mainly used when handling DRM video. * Refer to the EGL extension EGL_EXT_protected_content and GL extension * EXT_protected_textures for more information on how these buffers are expected * to behave. * The buffer is protected from direct CPU access or being read by * non-secure hardware, such as video encoders. * * This flag is incompatible with CPU read and write flags. It is * mainly used when handling DRM video. Refer to the EGL extension * EGL_EXT_protected_content and GL extension * GL_EXT_protected_textures for more information on how these * buffers are expected to behave. */ AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14, /// The buffer will be read by a hardware video encoder. Loading @@ -225,11 +232,17 @@ enum AHardwareBuffer_UsageFlags { AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24, /** * The buffer will be used as a cube map texture. * When this flag is present, the buffer must have a layer count that is * a multiple of 6. * When this flag is present, the buffer must have a layer count * that is a multiple of 6. Note that buffers with this flag must be * bound to OpenGL textures using the extension * GL_EXT_EGL_image_storage instead of GL_KHR_EGL_image. */ AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP = 1UL << 25, /// The buffer contains a complete mipmap hierarchy. /** * The buffer contains a complete mipmap hierarchy. * Note that buffers with this flag must be bound to OpenGL textures using * the extension GL_EXT_EGL_image_storage instead of GL_KHR_EGL_image. */ AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE = 1UL << 26, AHARDWAREBUFFER_USAGE_VENDOR_0 = 1ULL << 28, Loading @@ -255,13 +268,21 @@ enum AHardwareBuffer_UsageFlags { }; /** * Buffer description. Used for allocating new buffers and querying parameters * of existing ones. * Buffer description. Used for allocating new buffers and querying * parameters of existing ones. */ typedef struct AHardwareBuffer_Desc { uint32_t width; ///< Width in pixels. uint32_t height; ///< Height in pixels. uint32_t layers; ///< Number of images in an image array. /** * Number of images in an image array. AHardwareBuffers with one * layer correspond to regular 2D textures. AHardwareBuffers with * more than layer correspond to texture arrays. If the layer count * is a multiple of 6 and the usage flag * AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP is present, the buffer is * a cube map or a cube map array. */ uint32_t layers; uint32_t format; ///< One of AHardwareBuffer_Format. uint64_t usage; ///< Combination of AHardwareBuffer_UsageFlags. uint32_t stride; ///< Row stride in pixels, ignored for AHardwareBuffer_allocate() Loading Loading @@ -290,8 +311,10 @@ typedef struct AHardwareBuffer AHardwareBuffer; int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) __INTRODUCED_IN(26); /** * Acquire a reference on the given AHardwareBuffer object. This prevents the * object from being deleted until the last reference is removed. * Acquire a reference on the given AHardwareBuffer object. * * This prevents the object from being deleted until the last reference * is removed. */ void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26); Loading @@ -309,50 +332,73 @@ void AHardwareBuffer_describe(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26); /** * Lock the AHardwareBuffer for reading or writing, depending on the usage flags * passed. This call may block if the hardware needs to finish rendering or if * CPU caches need to be synchronized, or possibly for other implementation- * specific reasons. If fence is not negative, then it specifies a fence file * descriptor that will be signaled when the buffer is locked, otherwise the * caller will block until the buffer is available. * Lock the AHardwareBuffer for direct CPU access. * * If \a rect is not NULL, the caller promises to modify only data in the area * specified by rect. If rect is NULL, the caller may modify the contents of the * entire buffer. * This function can lock the buffer for either reading or writing. * It may block if the hardware needs to finish rendering, if CPU caches * need to be synchronized, or possibly for other implementation- * specific reasons. * * The content of the buffer outside of the specified rect is NOT modified * by this call. * The passed AHardwareBuffer must have one layer, otherwise the call * will fail. * * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*. If set, * then outVirtualAddress is filled with the address of the buffer in virtual * memory. * If \a fence is not negative, it specifies a fence file descriptor on * which to wait before locking the buffer. If it's negative, the caller * is responsible for ensuring that writes to the buffer have completed * before calling this function. Using this parameter is more efficient * than waiting on the fence and then calling this function. * * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*. * If set, then outVirtualAddress is filled with the address of the * buffer in virtual memory. The flags must also be compatible with * usage flags specified at buffer creation: if a read flag is passed, * the buffer must have been created with * AHARDWAREBUFFER_USAGE_CPU_READ_RARELY or * AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN. If a write flag is passed, it * must have been created with AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY or * AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN. * * THREADING CONSIDERATIONS: * If \a rect is not NULL, the caller promises to modify only data in * the area specified by rect. If rect is NULL, the caller may modify * the contents of the entire buffer. The content of the buffer outside * of the specified rect is NOT modified by this call. * * It is legal for several different threads to lock a buffer for read access; * none of the threads are blocked. * It is legal for several different threads to lock a buffer for read * access; none of the threads are blocked. * * Locking a buffer simultaneously for write or read/write is undefined, but * will neither terminate the process nor block the caller; AHardwareBuffer_lock * may return an error or leave the buffer's content into an indeterminate * state. * Locking a buffer simultaneously for write or read/write is undefined, * but will neither terminate the process nor block the caller. * AHardwareBuffer_lock may return an error or leave the buffer's * content in an indeterminate state. * * If the buffer has AHARDWAREBUFFER_FORMAT_BLOB, it is legal lock it * for reading and writing in multiple threads and/or processes * simultaneously, and the contents of the buffer behave like shared * memory. * * \return 0 on success, -EINVAL if \a buffer is NULL or if the usage * flags are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or an error * number of the lock fails for any reason. * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer * has more than one layer. Error number if the lock fails for any other * reason. */ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26); /** * Unlock the AHardwareBuffer; must be called after all changes to the buffer * are completed by the caller. If fence is not NULL then it will be set to a * file descriptor that is signaled when all pending work on the buffer is * completed. The caller is responsible for closing the fence when it is no * longer needed. * Unlock the AHardwareBuffer from direct CPU access. * * \return 0 on success, -EINVAL if \a buffer is NULL, or an error * number if the unlock fails for any reason. * Must be called after all changes to the buffer are completed by the * caller. If \a fence is NULL, the function will block until all work * is completed. Otherwise, \a fence will be set either to a valid file * descriptor or to -1. The file descriptor will become signaled once * the unlocking is complete and buffer contents are updated. * The caller is responsible for closing the file descriptor once it's * no longer needed. The value -1 indicates that unlocking has already * completed before the function returned and no further operations are * necessary. * * \return 0 on success. -EINVAL if \a buffer is NULL. Error number if * the unlock fails for any reason. */ int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED_IN(26); Loading @@ -365,7 +411,7 @@ int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd) __INTRODUCED_IN(26); /** * Receive the AHardwareBuffer from an AF_UNIX socket. * Receive an AHardwareBuffer from an AF_UNIX socket. * * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error * number if the operation fails for any reason. Loading @@ -374,6 +420,29 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out #endif // __ANDROID_API__ >= 26 #if __ANDROID_API__ >= 29 /** * Test whether the given format and usage flag combination is * allocatable. * * If this function returns true, it means that a buffer with the given * description can be allocated on this implementation, unless resource * exhaustion occurs. If this function returns false, it means that the * allocation of the given description will never succeed. * * The return value of this function may depend on all fields in the * description, except stride, which is always ignored. For example, * some implementations have implementation-defined limits on texture * size and layer count. * * \return 1 if the format and usage flag combination is allocatable, * 0 otherwise. */ int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) __INTRODUCED_IN(29); #endif // __ANDROID_API__ >= 29 __END_DECLS #endif // ANDROID_HARDWARE_BUFFER_H Loading
libs/nativewindow/libnativewindow.map.txt +1 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ LIBNATIVEWINDOW { AHardwareBuffer_createFromHandle; # vndk AHardwareBuffer_describe; AHardwareBuffer_getNativeHandle; # vndk AHardwareBuffer_isSupported; # introduced=29 AHardwareBuffer_lock; AHardwareBuffer_recvHandleFromUnixSocket; AHardwareBuffer_release; Loading