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

Commit 8d161a67 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add BGRA8888 format support." into qt-dev

parents 4ee2bc31 76512152
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");