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:
Changyeon Jo 2019-03-29 10:48:36 -07:00
parent 2f40bd0697
commit 7651215285
3 changed files with 98 additions and 24 deletions

View file

@ -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,

View file

@ -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);

View file

@ -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");