Loading libs/nativewindow/AHardwareBuffer.cpp +98 −37 Original line number Original line Diff line number Diff line Loading @@ -41,32 +41,10 @@ using namespace android; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) { int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) { if (!outBuffer || !desc) if (!outBuffer || !desc) return BAD_VALUE; return BAD_VALUE; if (!AHardwareBuffer_isValidDescription(desc, /*log=*/true)) return BAD_VALUE; if (!AHardwareBuffer_isValidPixelFormat(desc->format)) { ALOGE("Invalid AHardwareBuffer pixel format %u (%#x))", desc->format, desc->format); return BAD_VALUE; } int format = AHardwareBuffer_convertToPixelFormat(desc->format); 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); uint64_t usage = AHardwareBuffer_convertToGrallocUsageBits(desc->usage); sp<GraphicBuffer> gbuffer(new GraphicBuffer( sp<GraphicBuffer> gbuffer(new GraphicBuffer( desc->width, desc->height, format, desc->layers, usage, 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); 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; Rect bounds; if (!rect) { if (!rect) { bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight())); bounds.set(Rect(gbuffer->getWidth(), gbuffer->getHeight())); } else { } else { bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom)); 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) { int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) { Loading Loading @@ -274,6 +259,25 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out return NO_ERROR; 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 // VNDK functions Loading Loading @@ -322,14 +326,71 @@ int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* desc, namespace android { namespace android { // A 1:1 mapping of AHardwaqreBuffer bitmasks to gralloc1 bitmasks. bool AHardwareBuffer_isValidDescription(const AHardwareBuffer_Desc* desc, bool log) { struct UsageMaskMapping { if (desc->width == 0 || desc->height == 0 || desc->layers == 0) { uint64_t hardwareBufferMask; ALOGE_IF(log, "Width, height and layers must all be nonzero"); uint64_t grallocMask; return false; }; } static inline bool containsBits(uint64_t mask, uint64_t bitsToCheck) { if (!AHardwareBuffer_isValidPixelFormat(desc->format)) { return (mask & bitsToCheck) == bitsToCheck && bitsToCheck; 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) { 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"); "gralloc and AHardwareBuffer flags don't match"); static_assert(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE == (uint64_t)BufferUsage::GPU_TEXTURE, static_assert(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE == (uint64_t)BufferUsage::GPU_TEXTURE, "gralloc and AHardwareBuffer flags don't match"); "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"); "gralloc and AHardwareBuffer flags don't match"); static_assert(AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT == (uint64_t)BufferUsage::PROTECTED, static_assert(AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT == (uint64_t)BufferUsage::PROTECTED, "gralloc and AHardwareBuffer flags don't match"); "gralloc and AHardwareBuffer flags don't match"); Loading libs/nativewindow/include-private/private/android/AHardwareBufferHelpers.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -28,10 +28,15 @@ #include <stdint.h> #include <stdint.h> struct AHardwareBuffer; struct AHardwareBuffer; struct AHardwareBuffer_Desc; struct ANativeWindowBuffer; struct ANativeWindowBuffer; namespace android { 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 // whether this AHardwareBuffer format is valid bool AHardwareBuffer_isValidPixelFormat(uint32_t ahardwarebuffer_format); bool AHardwareBuffer_isValidPixelFormat(uint32_t ahardwarebuffer_format); Loading libs/nativewindow/include/android/hardware_buffer.h +122 −53 Original line number Original line Diff line number Diff line Loading @@ -102,8 +102,10 @@ enum AHardwareBuffer_Format { AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b, AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b, /** /** * An opaque binary blob format that must have height 1, with width equal to * Opaque binary blob format. * the buffer size in bytes. * 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, 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. /// The buffer will be written to by the GPU as a framebuffer attachment. AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER = 1UL << 9, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER = 1UL << 9, /** /** * The buffer will be written to by the GPU as a framebuffer attachment. * The buffer will be written to by the GPU as a framebuffer * Note that the name of this flag is somewhat misleading: it does not imply * attachment. * 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 * Note that the name of this flag is somewhat misleading: it does * this flag. * 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, AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, /** /** * The buffer is protected from direct CPU access or being read by non-secure * The buffer is protected from direct CPU access or being read by * hardware, such as video encoders. This flag is incompatible with CPU * non-secure hardware, such as video encoders. * read and write flags. It is mainly used when handling DRM video. * * Refer to the EGL extension EGL_EXT_protected_content and GL extension * This flag is incompatible with CPU read and write flags. It is * EXT_protected_textures for more information on how these buffers are expected * mainly used when handling DRM video. Refer to the EGL extension * to behave. * 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, AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14, /// The buffer will be read by a hardware video encoder. /// 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, AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24, /** /** * The buffer will be used as a cube map texture. * The buffer will be used as a cube map texture. * When this flag is present, the buffer must have a layer count that is * When this flag is present, the buffer must have a layer count * a multiple of 6. * 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, 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_GPU_MIPMAP_COMPLETE = 1UL << 26, AHARDWAREBUFFER_USAGE_VENDOR_0 = 1ULL << 28, AHARDWAREBUFFER_USAGE_VENDOR_0 = 1ULL << 28, Loading @@ -255,13 +268,21 @@ enum AHardwareBuffer_UsageFlags { }; }; /** /** * Buffer description. Used for allocating new buffers and querying parameters * Buffer description. Used for allocating new buffers and querying * of existing ones. * parameters of existing ones. */ */ typedef struct AHardwareBuffer_Desc { typedef struct AHardwareBuffer_Desc { uint32_t width; ///< Width in pixels. uint32_t width; ///< Width in pixels. uint32_t height; ///< Height 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. uint32_t format; ///< One of AHardwareBuffer_Format. uint64_t usage; ///< Combination of AHardwareBuffer_UsageFlags. uint64_t usage; ///< Combination of AHardwareBuffer_UsageFlags. uint32_t stride; ///< Row stride in pixels, ignored for AHardwareBuffer_allocate() 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, int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) __INTRODUCED_IN(26); AHardwareBuffer** outBuffer) __INTRODUCED_IN(26); /** /** * Acquire a reference on the given AHardwareBuffer object. This prevents the * Acquire a reference on the given AHardwareBuffer object. * object from being deleted until the last reference is removed. * * This prevents the object from being deleted until the last reference * is removed. */ */ void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26); 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); AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26); /** /** * Lock the AHardwareBuffer for reading or writing, depending on the usage flags * Lock the AHardwareBuffer for direct CPU access. * 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. * * * If \a rect is not NULL, the caller promises to modify only data in the area * This function can lock the buffer for either reading or writing. * specified by rect. If rect is NULL, the caller may modify the contents of the * It may block if the hardware needs to finish rendering, if CPU caches * entire buffer. * need to be synchronized, or possibly for other implementation- * specific reasons. * * * The content of the buffer outside of the specified rect is NOT modified * The passed AHardwareBuffer must have one layer, otherwise the call * by this call. * will fail. * * * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*. If set, * If \a fence is not negative, it specifies a fence file descriptor on * then outVirtualAddress is filled with the address of the buffer in virtual * which to wait before locking the buffer. If it's negative, the caller * memory. * 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; * It is legal for several different threads to lock a buffer for read * none of the threads are blocked. * access; none of the threads are blocked. * * * Locking a buffer simultaneously for write or read/write is undefined, but * Locking a buffer simultaneously for write or read/write is undefined, * will neither terminate the process nor block the caller; AHardwareBuffer_lock * but will neither terminate the process nor block the caller. * may return an error or leave the buffer's content into an indeterminate * AHardwareBuffer_lock may return an error or leave the buffer's * state. * 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 * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags * flags are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or an error * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer * number of the lock fails for any reason. * has more than one layer. Error number if the lock fails for any other * reason. */ */ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26); int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26); /** /** * Unlock the AHardwareBuffer; must be called after all changes to the buffer * Unlock the AHardwareBuffer from direct CPU access. * 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. * * * \return 0 on success, -EINVAL if \a buffer is NULL, or an error * Must be called after all changes to the buffer are completed by the * number if the unlock fails for any reason. * 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); 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); 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 * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error * number if the operation fails for any reason. * number if the operation fails for any reason. Loading @@ -374,6 +420,29 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out #endif // __ANDROID_API__ >= 26 #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 __END_DECLS #endif // ANDROID_HARDWARE_BUFFER_H #endif // ANDROID_HARDWARE_BUFFER_H Loading libs/nativewindow/libnativewindow.map.txt +1 −0 Original line number Original line Diff line number Diff line Loading @@ -5,6 +5,7 @@ LIBNATIVEWINDOW { AHardwareBuffer_createFromHandle; # vndk AHardwareBuffer_createFromHandle; # vndk AHardwareBuffer_describe; AHardwareBuffer_describe; AHardwareBuffer_getNativeHandle; # vndk AHardwareBuffer_getNativeHandle; # vndk AHardwareBuffer_isSupported; # introduced=29 AHardwareBuffer_lock; AHardwareBuffer_lock; AHardwareBuffer_recvHandleFromUnixSocket; AHardwareBuffer_recvHandleFromUnixSocket; AHardwareBuffer_release; AHardwareBuffer_release; Loading Loading
libs/nativewindow/AHardwareBuffer.cpp +98 −37 Original line number Original line Diff line number Diff line Loading @@ -41,32 +41,10 @@ using namespace android; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) { int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) { if (!outBuffer || !desc) if (!outBuffer || !desc) return BAD_VALUE; return BAD_VALUE; if (!AHardwareBuffer_isValidDescription(desc, /*log=*/true)) return BAD_VALUE; if (!AHardwareBuffer_isValidPixelFormat(desc->format)) { ALOGE("Invalid AHardwareBuffer pixel format %u (%#x))", desc->format, desc->format); return BAD_VALUE; } int format = AHardwareBuffer_convertToPixelFormat(desc->format); 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); uint64_t usage = AHardwareBuffer_convertToGrallocUsageBits(desc->usage); sp<GraphicBuffer> gbuffer(new GraphicBuffer( sp<GraphicBuffer> gbuffer(new GraphicBuffer( desc->width, desc->height, format, desc->layers, usage, 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); 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; Rect bounds; if (!rect) { if (!rect) { bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight())); bounds.set(Rect(gbuffer->getWidth(), gbuffer->getHeight())); } else { } else { bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom)); 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) { int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) { Loading Loading @@ -274,6 +259,25 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out return NO_ERROR; 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 // VNDK functions Loading Loading @@ -322,14 +326,71 @@ int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* desc, namespace android { namespace android { // A 1:1 mapping of AHardwaqreBuffer bitmasks to gralloc1 bitmasks. bool AHardwareBuffer_isValidDescription(const AHardwareBuffer_Desc* desc, bool log) { struct UsageMaskMapping { if (desc->width == 0 || desc->height == 0 || desc->layers == 0) { uint64_t hardwareBufferMask; ALOGE_IF(log, "Width, height and layers must all be nonzero"); uint64_t grallocMask; return false; }; } static inline bool containsBits(uint64_t mask, uint64_t bitsToCheck) { if (!AHardwareBuffer_isValidPixelFormat(desc->format)) { return (mask & bitsToCheck) == bitsToCheck && bitsToCheck; 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) { 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"); "gralloc and AHardwareBuffer flags don't match"); static_assert(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE == (uint64_t)BufferUsage::GPU_TEXTURE, static_assert(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE == (uint64_t)BufferUsage::GPU_TEXTURE, "gralloc and AHardwareBuffer flags don't match"); "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"); "gralloc and AHardwareBuffer flags don't match"); static_assert(AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT == (uint64_t)BufferUsage::PROTECTED, static_assert(AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT == (uint64_t)BufferUsage::PROTECTED, "gralloc and AHardwareBuffer flags don't match"); "gralloc and AHardwareBuffer flags don't match"); Loading
libs/nativewindow/include-private/private/android/AHardwareBufferHelpers.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -28,10 +28,15 @@ #include <stdint.h> #include <stdint.h> struct AHardwareBuffer; struct AHardwareBuffer; struct AHardwareBuffer_Desc; struct ANativeWindowBuffer; struct ANativeWindowBuffer; namespace android { 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 // whether this AHardwareBuffer format is valid bool AHardwareBuffer_isValidPixelFormat(uint32_t ahardwarebuffer_format); bool AHardwareBuffer_isValidPixelFormat(uint32_t ahardwarebuffer_format); Loading
libs/nativewindow/include/android/hardware_buffer.h +122 −53 Original line number Original line Diff line number Diff line Loading @@ -102,8 +102,10 @@ enum AHardwareBuffer_Format { AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b, AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b, /** /** * An opaque binary blob format that must have height 1, with width equal to * Opaque binary blob format. * the buffer size in bytes. * 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, 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. /// The buffer will be written to by the GPU as a framebuffer attachment. AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER = 1UL << 9, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER = 1UL << 9, /** /** * The buffer will be written to by the GPU as a framebuffer attachment. * The buffer will be written to by the GPU as a framebuffer * Note that the name of this flag is somewhat misleading: it does not imply * attachment. * 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 * Note that the name of this flag is somewhat misleading: it does * this flag. * 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, AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, /** /** * The buffer is protected from direct CPU access or being read by non-secure * The buffer is protected from direct CPU access or being read by * hardware, such as video encoders. This flag is incompatible with CPU * non-secure hardware, such as video encoders. * read and write flags. It is mainly used when handling DRM video. * * Refer to the EGL extension EGL_EXT_protected_content and GL extension * This flag is incompatible with CPU read and write flags. It is * EXT_protected_textures for more information on how these buffers are expected * mainly used when handling DRM video. Refer to the EGL extension * to behave. * 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, AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14, /// The buffer will be read by a hardware video encoder. /// 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, AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24, /** /** * The buffer will be used as a cube map texture. * The buffer will be used as a cube map texture. * When this flag is present, the buffer must have a layer count that is * When this flag is present, the buffer must have a layer count * a multiple of 6. * 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, 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_GPU_MIPMAP_COMPLETE = 1UL << 26, AHARDWAREBUFFER_USAGE_VENDOR_0 = 1ULL << 28, AHARDWAREBUFFER_USAGE_VENDOR_0 = 1ULL << 28, Loading @@ -255,13 +268,21 @@ enum AHardwareBuffer_UsageFlags { }; }; /** /** * Buffer description. Used for allocating new buffers and querying parameters * Buffer description. Used for allocating new buffers and querying * of existing ones. * parameters of existing ones. */ */ typedef struct AHardwareBuffer_Desc { typedef struct AHardwareBuffer_Desc { uint32_t width; ///< Width in pixels. uint32_t width; ///< Width in pixels. uint32_t height; ///< Height 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. uint32_t format; ///< One of AHardwareBuffer_Format. uint64_t usage; ///< Combination of AHardwareBuffer_UsageFlags. uint64_t usage; ///< Combination of AHardwareBuffer_UsageFlags. uint32_t stride; ///< Row stride in pixels, ignored for AHardwareBuffer_allocate() 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, int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer) __INTRODUCED_IN(26); AHardwareBuffer** outBuffer) __INTRODUCED_IN(26); /** /** * Acquire a reference on the given AHardwareBuffer object. This prevents the * Acquire a reference on the given AHardwareBuffer object. * object from being deleted until the last reference is removed. * * This prevents the object from being deleted until the last reference * is removed. */ */ void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26); 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); AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26); /** /** * Lock the AHardwareBuffer for reading or writing, depending on the usage flags * Lock the AHardwareBuffer for direct CPU access. * 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. * * * If \a rect is not NULL, the caller promises to modify only data in the area * This function can lock the buffer for either reading or writing. * specified by rect. If rect is NULL, the caller may modify the contents of the * It may block if the hardware needs to finish rendering, if CPU caches * entire buffer. * need to be synchronized, or possibly for other implementation- * specific reasons. * * * The content of the buffer outside of the specified rect is NOT modified * The passed AHardwareBuffer must have one layer, otherwise the call * by this call. * will fail. * * * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*. If set, * If \a fence is not negative, it specifies a fence file descriptor on * then outVirtualAddress is filled with the address of the buffer in virtual * which to wait before locking the buffer. If it's negative, the caller * memory. * 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; * It is legal for several different threads to lock a buffer for read * none of the threads are blocked. * access; none of the threads are blocked. * * * Locking a buffer simultaneously for write or read/write is undefined, but * Locking a buffer simultaneously for write or read/write is undefined, * will neither terminate the process nor block the caller; AHardwareBuffer_lock * but will neither terminate the process nor block the caller. * may return an error or leave the buffer's content into an indeterminate * AHardwareBuffer_lock may return an error or leave the buffer's * state. * 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 * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags * flags are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or an error * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer * number of the lock fails for any reason. * has more than one layer. Error number if the lock fails for any other * reason. */ */ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26); int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26); /** /** * Unlock the AHardwareBuffer; must be called after all changes to the buffer * Unlock the AHardwareBuffer from direct CPU access. * 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. * * * \return 0 on success, -EINVAL if \a buffer is NULL, or an error * Must be called after all changes to the buffer are completed by the * number if the unlock fails for any reason. * 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); 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); 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 * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error * number if the operation fails for any reason. * number if the operation fails for any reason. Loading @@ -374,6 +420,29 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out #endif // __ANDROID_API__ >= 26 #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 __END_DECLS #endif // ANDROID_HARDWARE_BUFFER_H #endif // ANDROID_HARDWARE_BUFFER_H Loading
libs/nativewindow/libnativewindow.map.txt +1 −0 Original line number Original line Diff line number Diff line Loading @@ -5,6 +5,7 @@ LIBNATIVEWINDOW { AHardwareBuffer_createFromHandle; # vndk AHardwareBuffer_createFromHandle; # vndk AHardwareBuffer_describe; AHardwareBuffer_describe; AHardwareBuffer_getNativeHandle; # vndk AHardwareBuffer_getNativeHandle; # vndk AHardwareBuffer_isSupported; # introduced=29 AHardwareBuffer_lock; AHardwareBuffer_lock; AHardwareBuffer_recvHandleFromUnixSocket; AHardwareBuffer_recvHandleFromUnixSocket; AHardwareBuffer_release; AHardwareBuffer_release; Loading