Loading libs/nativewindow/AHardwareBuffer.cpp +96 −1 Original line number Diff line number Diff line Loading @@ -122,6 +122,54 @@ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, return gbuffer->lockAsync(usage, usage, bounds, outVirtualAddress, fence); } int AHardwareBuffer_lockPlanes(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, AHardwareBuffer_Planes* outPlanes) { if (!buffer || !outPlanes) return BAD_VALUE; if (usage & ~(AHARDWAREBUFFER_USAGE_CPU_READ_MASK | AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) { ALOGE("Invalid usage flags passed to AHardwareBuffer_lock; only " " AHARDWAREBUFFER_USAGE_CPU_* flags are allowed"); return BAD_VALUE; } usage = AHardwareBuffer_convertToGrallocUsageBits(usage); GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer); Rect bounds; if (!rect) { bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight())); } else { bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom)); } int format = AHardwareBuffer_convertFromPixelFormat(uint32_t(gBuffer->getPixelFormat())); memset(outPlanes->planes, 0, sizeof(outPlanes->planes)); if (AHardwareBuffer_formatIsYuv(format)) { android_ycbcr yuvData; int result = gBuffer->lockAsyncYCbCr(usage, bounds, &yuvData, fence); if (result == 0) { outPlanes->planeCount = 3; outPlanes->planes[0].data = yuvData.y; outPlanes->planes[0].pixelStride = 1; outPlanes->planes[0].rowStride = yuvData.ystride; outPlanes->planes[1].data = yuvData.cb; outPlanes->planes[1].pixelStride = yuvData.chroma_step; outPlanes->planes[1].rowStride = yuvData.cstride; outPlanes->planes[2].data = yuvData.cr; outPlanes->planes[2].pixelStride = yuvData.chroma_step; outPlanes->planes[2].rowStride = yuvData.cstride; } else { outPlanes->planeCount = 0; } return result; } else { const uint32_t pixelStride = AHardwareBuffer_bytesPerPixel(format); outPlanes->planeCount = 1; outPlanes->planes[0].pixelStride = pixelStride; outPlanes->planes[0].rowStride = gBuffer->getStride() * pixelStride; return gBuffer->lockAsync(usage, usage, bounds, &outPlanes->planes[0].data, fence); } } int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) { if (!buffer) return BAD_VALUE; Loading Loading @@ -375,6 +423,19 @@ bool AHardwareBuffer_isValidDescription(const AHardwareBuffer_Desc* desc, bool l ALOGE_IF(log, "AHARDWAREBUFFER_FORMAT_BLOB cannot be encoded as video"); return false; } } else if (AHardwareBuffer_formatIsYuv(desc->format)) { if (desc->layers != 1) { ALOGE_IF(log, "Layers must be 1 for YUV formats."); return false; } const uint64_t yuvInvalidGpuMask = AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE | AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; if (desc->usage & yuvInvalidGpuMask) { ALOGE_IF(log, "Invalid usage flags specified for YUV format; " "mip-mapping and cube-mapping are not allowed."); return false; } } else { if (desc->usage & AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA) { ALOGE_IF(log, "AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA requires AHARDWAREBUFFER_FORMAT_BLOB"); Loading Loading @@ -474,6 +535,7 @@ bool AHardwareBuffer_isValidPixelFormat(uint32_t format) { case AHARDWAREBUFFER_FORMAT_D32_FLOAT: case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT: case AHARDWAREBUFFER_FORMAT_S8_UINT: case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: // VNDK formats only -- unfortunately we can't differentiate from where we're called case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM: case AHARDWAREBUFFER_FORMAT_YV12: Loading @@ -484,7 +546,6 @@ bool AHardwareBuffer_isValidPixelFormat(uint32_t format) { case AHARDWAREBUFFER_FORMAT_RAW12: case AHARDWAREBUFFER_FORMAT_RAW_OPAQUE: case AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED: case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: case AHARDWAREBUFFER_FORMAT_YCbCr_422_SP: case AHARDWAREBUFFER_FORMAT_YCrCb_420_SP: case AHARDWAREBUFFER_FORMAT_YCbCr_422_I: Loading @@ -495,6 +556,40 @@ bool AHardwareBuffer_isValidPixelFormat(uint32_t format) { } } bool AHardwareBuffer_formatIsYuv(uint32_t format) { switch (format) { case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: case AHARDWAREBUFFER_FORMAT_YV12: case AHARDWAREBUFFER_FORMAT_Y8: case AHARDWAREBUFFER_FORMAT_Y16: case AHARDWAREBUFFER_FORMAT_YCbCr_422_SP: case AHARDWAREBUFFER_FORMAT_YCrCb_420_SP: case AHARDWAREBUFFER_FORMAT_YCbCr_422_I: return true; default: return false; } } uint32_t AHardwareBuffer_bytesPerPixel(uint32_t format) { switch (format) { case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM: case AHARDWAREBUFFER_FORMAT_D16_UNORM: return 2; case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM: case AHARDWAREBUFFER_FORMAT_D24_UNORM: return 3; case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM: case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM: case AHARDWAREBUFFER_FORMAT_D32_FLOAT: case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM: case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT: return 4; default: return 0; } } uint32_t AHardwareBuffer_convertFromPixelFormat(uint32_t hal_format) { return hal_format; } Loading libs/nativewindow/include-private/private/android/AHardwareBufferHelpers.h +6 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,12 @@ bool AHardwareBuffer_isValidDescription(const AHardwareBuffer_Desc* desc, bool l // whether this AHardwareBuffer format is valid bool AHardwareBuffer_isValidPixelFormat(uint32_t ahardwarebuffer_format); // whether this is a YUV type format bool AHardwareBuffer_formatIsYuv(uint32_t format); // number of bytes per pixel or 0 if unknown or multi-planar uint32_t AHardwareBuffer_bytesPerPixel(uint32_t format); // convert AHardwareBuffer format to HAL format (note: this is a no-op) uint32_t AHardwareBuffer_convertFromPixelFormat(uint32_t format); Loading libs/nativewindow/include/android/hardware_buffer.h +55 −1 Original line number Diff line number Diff line Loading @@ -150,6 +150,14 @@ enum AHardwareBuffer_Format { * OpenGL ES: GL_STENCIL_INDEX8 */ AHARDWAREBUFFER_FORMAT_S8_UINT = 0x35, /** * YUV 420 888 format. * Must have an even width and height. Can be accessed in OpenGL * shaders through an external sampler. Does not support mip-maps * cube-maps or multi-layered textures. */ AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23, }; /** Loading Loading @@ -301,6 +309,24 @@ typedef struct AHardwareBuffer_Desc { uint64_t rfu1; ///< Initialize to zero, reserved for future use. } AHardwareBuffer_Desc; /** * Holds data for a single image plane. */ typedef struct AHardwareBuffer_Plane { void* data; ///< Points to first byte in plane uint32_t pixelStride; ///< Distance in bytes from the color channel of one pixel to the next uint32_t rowStride; ///< Distance in bytes from the first value of one row of the image to /// the first value of the next row. } AHardwareBuffer_Plane; /** * Holds all image planes that contain the pixel data. */ typedef struct AHardwareBuffer_Planes { uint32_t planeCount; ///< Number of distinct planes AHardwareBuffer_Plane planes[4]; ///< Array of image planes } AHardwareBuffer_Planes; /** * Opaque handle for a native hardware buffer. */ Loading Loading @@ -395,6 +421,34 @@ void AHardwareBuffer_describe(const AHardwareBuffer* buffer, int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26); /** * Lock a potentially multi-planar AHardwareBuffer for direct CPU access. * * This function is similar to AHardwareBuffer_lock, but can lock multi-planar * formats. The locked planes are returned in the \a outPlanes argument. Note, * that multi-planar should not be confused with multi-layer images, which this * locking function does not support. * * YUV formats are always represented by three separate planes of data, one for * each color plane. The order of planes in the array is guaranteed such that * plane #0 is always Y, plane #1 is always U (Cb), and plane #2 is always V * (Cr). All other formats are represented by a single plane. * * Additional information always accompanies the buffers, describing the row * stride and the pixel stride for each plane. * * In case the buffer cannot be locked, \a outPlanes will contain zero planes. * * See the AHardwareBuffer_lock documentation for all other locking semantics. * * \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_lockPlanes(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, AHardwareBuffer_Planes* outPlanes) __INTRODUCED_IN(29); /** * Unlock the AHardwareBuffer from direct CPU access. * Loading libs/nativewindow/include/vndk/hardware_buffer.h +0 −2 Original line number Diff line number Diff line Loading @@ -73,8 +73,6 @@ enum { AHARDWAREBUFFER_FORMAT_RAW_OPAQUE = 0x24, /* same as HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED */ AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED = 0x22, /* same as HAL_PIXEL_FORMAT_YCBCR_420_888 */ AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23, /* same as HAL_PIXEL_FORMAT_YCBCR_422_SP */ AHARDWAREBUFFER_FORMAT_YCbCr_422_SP = 0x10, /* same as HAL_PIXEL_FORMAT_YCRCB_420_SP */ Loading Loading
libs/nativewindow/AHardwareBuffer.cpp +96 −1 Original line number Diff line number Diff line Loading @@ -122,6 +122,54 @@ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, return gbuffer->lockAsync(usage, usage, bounds, outVirtualAddress, fence); } int AHardwareBuffer_lockPlanes(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, AHardwareBuffer_Planes* outPlanes) { if (!buffer || !outPlanes) return BAD_VALUE; if (usage & ~(AHARDWAREBUFFER_USAGE_CPU_READ_MASK | AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) { ALOGE("Invalid usage flags passed to AHardwareBuffer_lock; only " " AHARDWAREBUFFER_USAGE_CPU_* flags are allowed"); return BAD_VALUE; } usage = AHardwareBuffer_convertToGrallocUsageBits(usage); GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer); Rect bounds; if (!rect) { bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight())); } else { bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom)); } int format = AHardwareBuffer_convertFromPixelFormat(uint32_t(gBuffer->getPixelFormat())); memset(outPlanes->planes, 0, sizeof(outPlanes->planes)); if (AHardwareBuffer_formatIsYuv(format)) { android_ycbcr yuvData; int result = gBuffer->lockAsyncYCbCr(usage, bounds, &yuvData, fence); if (result == 0) { outPlanes->planeCount = 3; outPlanes->planes[0].data = yuvData.y; outPlanes->planes[0].pixelStride = 1; outPlanes->planes[0].rowStride = yuvData.ystride; outPlanes->planes[1].data = yuvData.cb; outPlanes->planes[1].pixelStride = yuvData.chroma_step; outPlanes->planes[1].rowStride = yuvData.cstride; outPlanes->planes[2].data = yuvData.cr; outPlanes->planes[2].pixelStride = yuvData.chroma_step; outPlanes->planes[2].rowStride = yuvData.cstride; } else { outPlanes->planeCount = 0; } return result; } else { const uint32_t pixelStride = AHardwareBuffer_bytesPerPixel(format); outPlanes->planeCount = 1; outPlanes->planes[0].pixelStride = pixelStride; outPlanes->planes[0].rowStride = gBuffer->getStride() * pixelStride; return gBuffer->lockAsync(usage, usage, bounds, &outPlanes->planes[0].data, fence); } } int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) { if (!buffer) return BAD_VALUE; Loading Loading @@ -375,6 +423,19 @@ bool AHardwareBuffer_isValidDescription(const AHardwareBuffer_Desc* desc, bool l ALOGE_IF(log, "AHARDWAREBUFFER_FORMAT_BLOB cannot be encoded as video"); return false; } } else if (AHardwareBuffer_formatIsYuv(desc->format)) { if (desc->layers != 1) { ALOGE_IF(log, "Layers must be 1 for YUV formats."); return false; } const uint64_t yuvInvalidGpuMask = AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE | AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; if (desc->usage & yuvInvalidGpuMask) { ALOGE_IF(log, "Invalid usage flags specified for YUV format; " "mip-mapping and cube-mapping are not allowed."); return false; } } else { if (desc->usage & AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA) { ALOGE_IF(log, "AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA requires AHARDWAREBUFFER_FORMAT_BLOB"); Loading Loading @@ -474,6 +535,7 @@ bool AHardwareBuffer_isValidPixelFormat(uint32_t format) { case AHARDWAREBUFFER_FORMAT_D32_FLOAT: case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT: case AHARDWAREBUFFER_FORMAT_S8_UINT: case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: // VNDK formats only -- unfortunately we can't differentiate from where we're called case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM: case AHARDWAREBUFFER_FORMAT_YV12: Loading @@ -484,7 +546,6 @@ bool AHardwareBuffer_isValidPixelFormat(uint32_t format) { case AHARDWAREBUFFER_FORMAT_RAW12: case AHARDWAREBUFFER_FORMAT_RAW_OPAQUE: case AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED: case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: case AHARDWAREBUFFER_FORMAT_YCbCr_422_SP: case AHARDWAREBUFFER_FORMAT_YCrCb_420_SP: case AHARDWAREBUFFER_FORMAT_YCbCr_422_I: Loading @@ -495,6 +556,40 @@ bool AHardwareBuffer_isValidPixelFormat(uint32_t format) { } } bool AHardwareBuffer_formatIsYuv(uint32_t format) { switch (format) { case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: case AHARDWAREBUFFER_FORMAT_YV12: case AHARDWAREBUFFER_FORMAT_Y8: case AHARDWAREBUFFER_FORMAT_Y16: case AHARDWAREBUFFER_FORMAT_YCbCr_422_SP: case AHARDWAREBUFFER_FORMAT_YCrCb_420_SP: case AHARDWAREBUFFER_FORMAT_YCbCr_422_I: return true; default: return false; } } uint32_t AHardwareBuffer_bytesPerPixel(uint32_t format) { switch (format) { case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM: case AHARDWAREBUFFER_FORMAT_D16_UNORM: return 2; case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM: case AHARDWAREBUFFER_FORMAT_D24_UNORM: return 3; case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM: case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM: case AHARDWAREBUFFER_FORMAT_D32_FLOAT: case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM: case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT: return 4; default: return 0; } } uint32_t AHardwareBuffer_convertFromPixelFormat(uint32_t hal_format) { return hal_format; } Loading
libs/nativewindow/include-private/private/android/AHardwareBufferHelpers.h +6 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,12 @@ bool AHardwareBuffer_isValidDescription(const AHardwareBuffer_Desc* desc, bool l // whether this AHardwareBuffer format is valid bool AHardwareBuffer_isValidPixelFormat(uint32_t ahardwarebuffer_format); // whether this is a YUV type format bool AHardwareBuffer_formatIsYuv(uint32_t format); // number of bytes per pixel or 0 if unknown or multi-planar uint32_t AHardwareBuffer_bytesPerPixel(uint32_t format); // convert AHardwareBuffer format to HAL format (note: this is a no-op) uint32_t AHardwareBuffer_convertFromPixelFormat(uint32_t format); Loading
libs/nativewindow/include/android/hardware_buffer.h +55 −1 Original line number Diff line number Diff line Loading @@ -150,6 +150,14 @@ enum AHardwareBuffer_Format { * OpenGL ES: GL_STENCIL_INDEX8 */ AHARDWAREBUFFER_FORMAT_S8_UINT = 0x35, /** * YUV 420 888 format. * Must have an even width and height. Can be accessed in OpenGL * shaders through an external sampler. Does not support mip-maps * cube-maps or multi-layered textures. */ AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23, }; /** Loading Loading @@ -301,6 +309,24 @@ typedef struct AHardwareBuffer_Desc { uint64_t rfu1; ///< Initialize to zero, reserved for future use. } AHardwareBuffer_Desc; /** * Holds data for a single image plane. */ typedef struct AHardwareBuffer_Plane { void* data; ///< Points to first byte in plane uint32_t pixelStride; ///< Distance in bytes from the color channel of one pixel to the next uint32_t rowStride; ///< Distance in bytes from the first value of one row of the image to /// the first value of the next row. } AHardwareBuffer_Plane; /** * Holds all image planes that contain the pixel data. */ typedef struct AHardwareBuffer_Planes { uint32_t planeCount; ///< Number of distinct planes AHardwareBuffer_Plane planes[4]; ///< Array of image planes } AHardwareBuffer_Planes; /** * Opaque handle for a native hardware buffer. */ Loading Loading @@ -395,6 +421,34 @@ void AHardwareBuffer_describe(const AHardwareBuffer* buffer, int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26); /** * Lock a potentially multi-planar AHardwareBuffer for direct CPU access. * * This function is similar to AHardwareBuffer_lock, but can lock multi-planar * formats. The locked planes are returned in the \a outPlanes argument. Note, * that multi-planar should not be confused with multi-layer images, which this * locking function does not support. * * YUV formats are always represented by three separate planes of data, one for * each color plane. The order of planes in the array is guaranteed such that * plane #0 is always Y, plane #1 is always U (Cb), and plane #2 is always V * (Cr). All other formats are represented by a single plane. * * Additional information always accompanies the buffers, describing the row * stride and the pixel stride for each plane. * * In case the buffer cannot be locked, \a outPlanes will contain zero planes. * * See the AHardwareBuffer_lock documentation for all other locking semantics. * * \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_lockPlanes(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, AHardwareBuffer_Planes* outPlanes) __INTRODUCED_IN(29); /** * Unlock the AHardwareBuffer from direct CPU access. * Loading
libs/nativewindow/include/vndk/hardware_buffer.h +0 −2 Original line number Diff line number Diff line Loading @@ -73,8 +73,6 @@ enum { AHARDWAREBUFFER_FORMAT_RAW_OPAQUE = 0x24, /* same as HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED */ AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED = 0x22, /* same as HAL_PIXEL_FORMAT_YCBCR_420_888 */ AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23, /* same as HAL_PIXEL_FORMAT_YCBCR_422_SP */ AHARDWAREBUFFER_FORMAT_YCbCr_422_SP = 0x10, /* same as HAL_PIXEL_FORMAT_YCRCB_420_SP */ Loading