Add BGRA8888 format support.
Bug: 129462449
Test: Build and run VTS on Hawk
Change-Id: I9d162b3200b64fbbec802eb1b0a2b6862af6949b
Signed-off-by: Changyeon Jo <changyeon@google.com>
(cherry picked from commit af09bfeed4
)
This commit is contained in:
parent
2f40bd0697
commit
7651215285
3 changed files with 98 additions and 24 deletions
|
@ -38,7 +38,8 @@ static inline float clamp(float v, float min, float max) {
|
|||
}
|
||||
|
||||
|
||||
static uint32_t yuvToRgbx(const unsigned char Y, const unsigned char Uin, const unsigned char Vin) {
|
||||
static uint32_t yuvToRgbx(const unsigned char Y, const unsigned char Uin, const unsigned char Vin,
|
||||
bool bgrxFormat = false) {
|
||||
// Don't use this if you want to see the best performance. :)
|
||||
// Better to do this in a pixel shader if we really have to, but on actual
|
||||
// embedded hardware we expect to be able to texture directly from the YUV data
|
||||
|
@ -52,16 +53,24 @@ static uint32_t yuvToRgbx(const unsigned char Y, const unsigned char Uin, const
|
|||
unsigned char G = (unsigned char)clamp(Gf, 0.0f, 255.0f);
|
||||
unsigned char B = (unsigned char)clamp(Bf, 0.0f, 255.0f);
|
||||
|
||||
return (R ) |
|
||||
(G << 8) |
|
||||
(B << 16) |
|
||||
0xFF000000; // Fill the alpha channel with ones
|
||||
if (!bgrxFormat) {
|
||||
return (R ) |
|
||||
(G << 8) |
|
||||
(B << 16) |
|
||||
0xFF000000; // Fill the alpha channel with ones
|
||||
} else {
|
||||
return (R << 16) |
|
||||
(G << 8) |
|
||||
(B ) |
|
||||
0xFF000000; // Fill the alpha channel with ones
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void copyNV21toRGB32(unsigned width, unsigned height,
|
||||
uint8_t* src,
|
||||
uint32_t* dst, unsigned dstStridePixels)
|
||||
uint32_t* dst, unsigned dstStridePixels,
|
||||
bool bgrxFormat)
|
||||
{
|
||||
// The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleaved
|
||||
// U/V array. It assumes an even width and height for the overall image, and a horizontal
|
||||
|
@ -84,7 +93,7 @@ void copyNV21toRGB32(unsigned width, unsigned height,
|
|||
for (unsigned c = 0; c < width; c++) {
|
||||
unsigned uCol = (c & ~1); // uCol is always even and repeats 1:2 with Y values
|
||||
unsigned vCol = uCol | 1; // vCol is always odd
|
||||
rowDest[c] = yuvToRgbx(rowY[c], rowUV[uCol], rowUV[vCol]);
|
||||
rowDest[c] = yuvToRgbx(rowY[c], rowUV[uCol], rowUV[vCol], bgrxFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +101,8 @@ void copyNV21toRGB32(unsigned width, unsigned height,
|
|||
|
||||
void copyYV12toRGB32(unsigned width, unsigned height,
|
||||
uint8_t* src,
|
||||
uint32_t* dst, unsigned dstStridePixels)
|
||||
uint32_t* dst, unsigned dstStridePixels,
|
||||
bool bgrxFormat)
|
||||
{
|
||||
// The YV12 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 U array, followed
|
||||
// by another 1/2 x 1/2 V array. It assumes an even width and height for the overall image,
|
||||
|
@ -118,7 +128,7 @@ void copyYV12toRGB32(unsigned width, unsigned height,
|
|||
uint32_t* rowDest = dst + r*dstStridePixels;
|
||||
|
||||
for (unsigned c = 0; c < width; c++) {
|
||||
rowDest[c] = yuvToRgbx(rowY[c], rowU[c], rowV[c]);
|
||||
rowDest[c] = yuvToRgbx(rowY[c], rowU[c], rowV[c], bgrxFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +136,8 @@ void copyYV12toRGB32(unsigned width, unsigned height,
|
|||
|
||||
void copyYUYVtoRGB32(unsigned width, unsigned height,
|
||||
uint8_t* src, unsigned srcStridePixels,
|
||||
uint32_t* dst, unsigned dstStridePixels)
|
||||
uint32_t* dst, unsigned dstStridePixels,
|
||||
bool bgrxFormat)
|
||||
{
|
||||
uint32_t* srcWords = (uint32_t*)src;
|
||||
|
||||
|
@ -144,8 +155,8 @@ void copyYUYVtoRGB32(unsigned width, unsigned height,
|
|||
uint8_t V = (srcPixel >> 24) & 0xFF;
|
||||
|
||||
// On the RGB output, we're writing one pixel at a time
|
||||
*(dst+0) = yuvToRgbx(Y1, U, V);
|
||||
*(dst+1) = yuvToRgbx(Y2, U, V);
|
||||
*(dst+0) = yuvToRgbx(Y1, U, V, bgrxFormat);
|
||||
*(dst+1) = yuvToRgbx(Y2, U, V, bgrxFormat);
|
||||
dst += 2;
|
||||
}
|
||||
|
||||
|
@ -156,6 +167,30 @@ void copyYUYVtoRGB32(unsigned width, unsigned height,
|
|||
}
|
||||
|
||||
|
||||
void copyNV21toBGR32(unsigned width, unsigned height,
|
||||
uint8_t* src,
|
||||
uint32_t* dst, unsigned dstStridePixels)
|
||||
{
|
||||
return copyNV21toRGB32(width, height, src, dst, dstStridePixels, true);
|
||||
}
|
||||
|
||||
|
||||
void copyYV12toBGR32(unsigned width, unsigned height,
|
||||
uint8_t* src,
|
||||
uint32_t* dst, unsigned dstStridePixels)
|
||||
{
|
||||
return copyYV12toRGB32(width, height, src, dst, dstStridePixels, true);
|
||||
}
|
||||
|
||||
|
||||
void copyYUYVtoBGR32(unsigned width, unsigned height,
|
||||
uint8_t* src, unsigned srcStridePixels,
|
||||
uint32_t* dst, unsigned dstStridePixels)
|
||||
{
|
||||
return copyYUYVtoRGB32(width, height, src, srcStridePixels, dst, dstStridePixels, true);
|
||||
}
|
||||
|
||||
|
||||
void copyMatchedInterleavedFormats(unsigned width, unsigned height,
|
||||
void* src, unsigned srcStridePixels,
|
||||
void* dst, unsigned dstStridePixels,
|
||||
|
|
|
@ -21,30 +21,44 @@
|
|||
#include <stdint.h>
|
||||
|
||||
|
||||
// Given an image buffer in NV21 format (HAL_PIXEL_FORMAT_YCRCB_420_SP), output 32bit RGBx values.
|
||||
// The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleaved
|
||||
// Given an image buffer in NV21 format (HAL_PIXEL_FORMAT_YCRCB_420_SP), output 32bit RGBx/BGRx
|
||||
// values. The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleaved
|
||||
// U/V array. It assumes an even width and height for the overall image, and a horizontal
|
||||
// stride that is an even multiple of 16 bytes for both the Y and UV arrays.
|
||||
void copyNV21toRGB32(unsigned width, unsigned height,
|
||||
uint8_t* src,
|
||||
uint32_t* dst, unsigned dstStridePixels,
|
||||
bool bgrxFormat = false);
|
||||
|
||||
void copyNV21toBGR32(unsigned width, unsigned height,
|
||||
uint8_t* src,
|
||||
uint32_t* dst, unsigned dstStridePixels);
|
||||
|
||||
|
||||
// Given an image buffer in YV12 format (HAL_PIXEL_FORMAT_YV12), output 32bit RGBx values.
|
||||
// Given an image buffer in YV12 format (HAL_PIXEL_FORMAT_YV12), output 32bit RGBx/BGRx values.
|
||||
// The YV12 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 U array, followed
|
||||
// by another 1/2 x 1/2 V array. It assumes an even width and height for the overall image,
|
||||
// and a horizontal stride that is an even multiple of 16 bytes for each of the Y, U,
|
||||
// and V arrays.
|
||||
void copyYV12toRGB32(unsigned width, unsigned height,
|
||||
uint8_t* src,
|
||||
uint32_t* dst, unsigned dstStridePixels,
|
||||
bool bgrxFormat = false);
|
||||
|
||||
void copyYV12toBGR32(unsigned width, unsigned height,
|
||||
uint8_t* src,
|
||||
uint32_t* dst, unsigned dstStridePixels);
|
||||
|
||||
|
||||
// Given an image buffer in YUYV format (HAL_PIXEL_FORMAT_YCBCR_422_I), output 32bit RGBx values.
|
||||
// The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleaved
|
||||
// Given an image buffer in YUYV format (HAL_PIXEL_FORMAT_YCBCR_422_I), output 32bit RGBx/BGRx
|
||||
// values. The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleaved
|
||||
// U/V array. It assumes an even width and height for the overall image, and a horizontal
|
||||
// stride that is an even multiple of 16 bytes for both the Y and UV arrays.
|
||||
void copyYUYVtoRGB32(unsigned width, unsigned height,
|
||||
uint8_t* src, unsigned srcStrideBytes,
|
||||
uint32_t* dst, unsigned dstStrideBytes,
|
||||
bool bgrxFormat = false);
|
||||
|
||||
void copyYUYVtoBGR32(unsigned width, unsigned height,
|
||||
uint8_t* src, unsigned srcStrideBytes,
|
||||
uint32_t* dst, unsigned dstStrideBytes);
|
||||
|
||||
|
|
|
@ -231,16 +231,12 @@ bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer,
|
|||
uint8_t* srcPixels = nullptr;
|
||||
src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels);
|
||||
|
||||
// Lock our target buffer for writing (should be RGBA8888 format)
|
||||
// Lock our target buffer for writing (should be either RGBA8888 or BGRA8888 format)
|
||||
uint32_t* tgtPixels = nullptr;
|
||||
tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels);
|
||||
|
||||
if (srcPixels && tgtPixels) {
|
||||
if (tgtBuffer.format != HAL_PIXEL_FORMAT_RGBA_8888) {
|
||||
// We always expect 32 bit RGB for the display output for now. Is there a need for 565?
|
||||
ALOGE("Diplay buffer is always expected to be 32bit RGBA");
|
||||
success = false;
|
||||
} else {
|
||||
if (tgtBuffer.format == HAL_PIXEL_FORMAT_RGBA_8888) {
|
||||
if (srcBuffer.format == HAL_PIXEL_FORMAT_YCRCB_420_SP) { // 420SP == NV21
|
||||
copyNV21toRGB32(width, height,
|
||||
srcPixels,
|
||||
|
@ -258,7 +254,36 @@ bool FrameHandler::copyBufferContents(const BufferDesc& tgtBuffer,
|
|||
srcPixels, srcBuffer.stride,
|
||||
tgtPixels, tgtBuffer.stride,
|
||||
tgtBuffer.pixelSize);
|
||||
} else {
|
||||
ALOGE("Camera buffer format is not supported");
|
||||
success = false;
|
||||
}
|
||||
} else if (tgtBuffer.format == HAL_PIXEL_FORMAT_BGRA_8888) {
|
||||
if (srcBuffer.format == HAL_PIXEL_FORMAT_YCRCB_420_SP) { // 420SP == NV21
|
||||
copyNV21toBGR32(width, height,
|
||||
srcPixels,
|
||||
tgtPixels, tgtBuffer.stride);
|
||||
} else if (srcBuffer.format == HAL_PIXEL_FORMAT_YV12) { // YUV_420P == YV12
|
||||
copyYV12toBGR32(width, height,
|
||||
srcPixels,
|
||||
tgtPixels, tgtBuffer.stride);
|
||||
} else if (srcBuffer.format == HAL_PIXEL_FORMAT_YCBCR_422_I) { // YUYV
|
||||
copyYUYVtoBGR32(width, height,
|
||||
srcPixels, srcBuffer.stride,
|
||||
tgtPixels, tgtBuffer.stride);
|
||||
} else if (srcBuffer.format == tgtBuffer.format) { // 32bit RGBA
|
||||
copyMatchedInterleavedFormats(width, height,
|
||||
srcPixels, srcBuffer.stride,
|
||||
tgtPixels, tgtBuffer.stride,
|
||||
tgtBuffer.pixelSize);
|
||||
} else {
|
||||
ALOGE("Camera buffer format is not supported");
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
// We always expect 32 bit RGB for the display output for now. Is there a need for 565?
|
||||
ALOGE("Diplay buffer is always expected to be 32bit RGBA");
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
ALOGE("Failed to lock buffer contents for contents transfer");
|
||||
|
|
Loading…
Reference in a new issue