Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e38163d authored by Changyeon Jo's avatar Changyeon Jo Committed by Android (Google) Code Review
Browse files

Merge "Add BGRA8888 format support."

parents c2ce5f2c af09bfee
Loading
Loading
Loading
Loading
+47 −12
Original line number Diff line number Diff line
@@ -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);

    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,
+20 −6
Original line number Diff line number Diff line
@@ -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);
                     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);

+31 −6
Original line number Diff line number Diff line
@@ -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");