goldfish-opengl: fix conversion between yuv and rgb888

Also fix crash in non DMA yuv to rgb888 conversion.

BUG: 131917231
Change-Id: Icadd9424cc58ed2dfb786a68cc66ae6fa5310d0c
diff --git a/system/OpenglSystemCommon/FormatConversions.cpp b/system/OpenglSystemCommon/FormatConversions.cpp
index 53f0e83..92d7f0b 100644
--- a/system/OpenglSystemCommon/FormatConversions.cpp
+++ b/system/OpenglSystemCommon/FormatConversions.cpp
@@ -20,6 +20,7 @@
 #include <log/log.h>
 #endif
 #include <string.h>
+#include <stdio.h>
 
 #define DEBUG 0
 
@@ -90,7 +91,7 @@
         uint8_t *yv12_y = yv12_y0 + j * yStride;
         uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
         uint8_t *yv12_u = yv12_v + cSize;
-        uint16_t *rgb_ptr = rgb_ptr0 + get_rgb_offset(j, width, rgb_stride);
+        uint16_t *rgb_ptr = rgb_ptr0 + get_rgb_offset(j, width, rgb_stride) / 2;
         bool jeven = (j & 1) == 0;
         for (int i = left; i <= right; ++i) {
             uint8_t r = ((rgb_ptr[i]) >> 11) & 0x01f;
@@ -127,12 +128,26 @@
 
     uint8_t *rgb_ptr0 = (uint8_t *)src;
     uint8_t *yv12_y0 = (uint8_t *)dest;
+    uint8_t *yv12_u0 = yv12_y0 + yStride * height + cSize;
     uint8_t *yv12_v0 = yv12_y0 + yStride * height;
 
+#if DEBUG
+    char mybuf[1024];
+    snprintf(mybuf, sizeof(mybuf), "/sdcard/raw_%d_%d_rgb.ppm", width, height);
+    FILE *myfp = fopen(mybuf, "wb"); /* b - binary mode */
+    (void) fprintf(myfp, "P6\n%d %d\n255\n", width, height);
+
+    if (myfp == NULL) {
+        DD("failed to open /sdcard/raw_rgb888.ppm");
+    } else {
+        fwrite(rgb_ptr0, width * height * rgb_stride, 1, myfp);
+        fclose(myfp);
+    }
+#endif
+
+    int uvcount = 0;
     for (int j = top; j <= bottom; ++j) {
         uint8_t *yv12_y = yv12_y0 + j * yStride;
-        uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
-        uint8_t *yv12_u = yv12_v + cSize;
         uint8_t *rgb_ptr = rgb_ptr0 + get_rgb_offset(j, width, rgb_stride);
         bool jeven = (j & 1) == 0;
         for (int i = left; i <= right; ++i) {
@@ -140,15 +155,32 @@
             uint8_t G = rgb_ptr[i*rgb_stride+1];
             uint8_t B = rgb_ptr[i*rgb_stride+2];
             // convert to YV12
-            // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
-            yv12_y[i] = clamp_rgb((77 * R + 150 * G +  29 * B) >> 8);
+            // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
+            // but scale up U by 1/0.96
+            yv12_y[i] = clamp_rgb(1.0 * ((0.25678823529411765 * R) + (0.5041294117647058 * G) + (0.09790588235294118 * B)) + 16);
             bool ieven = (i & 1) == 0;
             if (jeven && ieven) {
-                yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
-                yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
+                yv12_u0[uvcount] = clamp_rgb((1/0.96) * (-(0.1482235294117647 * R) - (0.2909921568627451 * G) + (0.4392156862745098 * B)) + 128);
+                yv12_v0[uvcount] = clamp_rgb((1.0)* ((0.4392156862745098 * R) - (0.36778823529411764 * G) - (0.07142745098039215 * B)) + 128);
+                uvcount ++;
             }
         }
+        if (jeven) {
+            yv12_u0 += cStride;
+            yv12_v0 += cStride;
+            uvcount = 0;
+        }
     }
+
+#if DEBUG
+    snprintf(mybuf, sizeof(mybuf), "/sdcard/raw_%d_%d_yv12.yuv", width, height);
+    FILE *yuvfp = fopen(mybuf, "wb"); /* b - binary mode */
+    if (yuvfp != NULL) {
+        fwrite(yv12_y0, yStride * height + 2 * cSize, 1, yuvfp);
+        fclose(yuvfp);
+    }
+#endif
+
 }
 
 void rgb888_to_yuv420p(char* dest, char* src, int width, int height,
@@ -256,20 +288,15 @@
         uint8_t *rgb_ptr = rgb_ptr0 + get_rgb_offset(j - top, right - left + 1, rgb_stride);
         for (int i = left; i <= right; ++i) {
             // convert to rgb
-            // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
+            // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
+            // but scale down U by 0.96 to mitigate rgb over/under flow
             signed y1 = (signed)yv12_y[i] - 16;
             signed u = (signed)yv12_u[i / 2] - 128;
             signed v = (signed)yv12_v[i / 2] - 128;
 
-            signed u_b = u * 517;
-            signed u_g = -u * 100;
-            signed v_g = -v * 208;
-            signed v_r = v * 409;
-
-            signed tmp1 = y1 * 298;
-            signed b1 = clamp_rgb((tmp1 + u_b) / 256);
-            signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
-            signed r1 = clamp_rgb((tmp1 + v_r) / 256);
+            signed r1 = clamp_rgb(1 * (1.1643835616438356 * y1 + 1.5960267857142856 * v));
+            signed g1 = clamp_rgb(1 * (1.1643835616438356 * y1 - 0.39176229009491365 * u * 0.97  - 0.8129676472377708 * v));
+            signed b1 = clamp_rgb(1 * (1.1643835616438356 * y1 + 2.017232142857143 * u * 0.97));
 
             rgb_ptr[(i-left)*rgb_stride] = r1;
             rgb_ptr[(i-left)*rgb_stride+1] = g1;
diff --git a/system/gralloc/gralloc.cpp b/system/gralloc/gralloc.cpp
index 725848e..e63e048 100644
--- a/system/gralloc/gralloc.cpp
+++ b/system/gralloc/gralloc.cpp
@@ -209,10 +209,10 @@
     if (new_sz != grdma->sz) {
         if (new_sz > MAX_DMA_SIZE)  {
             D("%s: requested sz %u too large (limit %u), set to fallback.",
-              __func__, sz, MAX_DMA_SIZE);
+              __func__, new_sz, MAX_DMA_SIZE);
             grdma->bigbufCount++;
         } else {
-            D("%s: change sz from %u to %u", __func__, grdma->sz, sz);
+            D("%s: change sz from %u to %u", __func__, grdma->sz, new_sz);
             resize_gralloc_dmaregion_locked(grdma, new_sz);
         }
     }
@@ -429,12 +429,18 @@
                 to_send, send_buffer_size);
         pthread_mutex_unlock(&grdma->lock);
     } else {
+        char *tmpBuf = nullptr;
         if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
+            tmpBuf = new char[cb->lockedWidth * cb->lockedHeight * bpp];
+            D("convert yv12 to rgb888 here");
+            to_send = tmpBuf;
             yv12_to_rgb888(to_send, pixels,
                            width, height, left, top,
                            left + width - 1, top + height - 1);
         }
         if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+            tmpBuf = new char[cb->lockedWidth * cb->lockedHeight * bpp];
+            to_send = tmpBuf;
             yuv420p_to_rgb888(to_send, pixels,
                               width, height, left, top,
                               left + width - 1, top + height - 1);
@@ -442,6 +448,9 @@
         rcEnc->rcUpdateColorBuffer(rcEnc, cb->hostHandle,
                 left, top, width, height,
                 cb->glFormat, cb->glType, to_send);
+        if (tmpBuf != nullptr) {
+            delete [] tmpBuf;
+        }
     }
 }
 
@@ -1219,6 +1228,7 @@
                     0, 0, cb->width, cb->height, cb->glFormat, cb->glType, rgb_addr);
             if (tmpBuf) {
                 if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
+                    D("convert rgb888 to yv12 here");
                     rgb888_to_yv12((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);
                 } else if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
                     rgb888_to_yuv420p((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);