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 af09bfeed4f2f4bfc1bffeb6974e9010cbcf203e)
diff --git a/automotive/evs/1.0/vts/functional/FormatConvert.cpp b/automotive/evs/1.0/vts/functional/FormatConvert.cpp
index 1e8929d..3d82d32 100644
--- a/automotive/evs/1.0/vts/functional/FormatConvert.cpp
+++ b/automotive/evs/1.0/vts/functional/FormatConvert.cpp
@@ -38,7 +38,8 @@
 }
 
 
-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 @@
     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 @@
         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 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 @@
         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 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 @@
             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 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,
diff --git a/automotive/evs/1.0/vts/functional/FormatConvert.h b/automotive/evs/1.0/vts/functional/FormatConvert.h
index 3ff1eec..4a94f99 100644
--- a/automotive/evs/1.0/vts/functional/FormatConvert.h
+++ b/automotive/evs/1.0/vts/functional/FormatConvert.h
@@ -21,31 +21,45 @@
 #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);
 
 
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.cpp b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
index a69f72b..d44ba41 100644
--- a/automotive/evs/1.0/vts/functional/FrameHandler.cpp
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
@@ -231,16 +231,12 @@
     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 @@
                                               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");