Enable wide color gamut rendering

When wide color gamut rendering is requested, hwui will now
use an rgba16f scRGB-nl surface for rendering. This change
also fixes the way screenshots are handled in the platform
to behave properly with wide gamut rendering.

This change does not affect hardware layers. They also
need to use rgba16f scRGB-nl; this will be addressed in
another CL.

Bug: 29940137
Test: CtsUiRenderingTestCases, CtsGraphicsTestCases

Change-Id: I68fd96c451652136c566ec48fb0e97c2a7a257c5
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 5fedc9e..607e6e0 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -33,17 +33,24 @@
 #include <ui/DisplayInfo.h>
 #include <ui/PixelFormat.h>
 
+#include <system/graphics.h>
+
 // TODO: Fix Skia.
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-parameter"
 #include <SkImageEncoder.h>
 #include <SkData.h>
+#include <SkColorSpace.h>
 #pragma GCC diagnostic pop
 
 using namespace android;
 
 static uint32_t DEFAULT_DISPLAY_ID = ISurfaceComposer::eDisplayIdMain;
 
+#define COLORSPACE_UNKNOWN    0
+#define COLORSPACE_SRGB       1
+#define COLORSPACE_DISPLAY_P3 2
+
 static void usage(const char* pname)
 {
     fprintf(stderr,
@@ -67,6 +74,31 @@
     }
 }
 
+static sk_sp<SkColorSpace> dataSpaceToColorSpace(android_dataspace d)
+{
+    switch (d) {
+        case HAL_DATASPACE_V0_SRGB:
+            return SkColorSpace::MakeSRGB();
+        case HAL_DATASPACE_DISPLAY_P3:
+            return SkColorSpace::MakeRGB(
+                    SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut);
+        default:
+            return nullptr;
+    }
+}
+
+static uint32_t dataSpaceToInt(android_dataspace d)
+{
+    switch (d) {
+        case HAL_DATASPACE_V0_SRGB:
+            return COLORSPACE_SRGB;
+        case HAL_DATASPACE_DISPLAY_P3:
+            return COLORSPACE_DISPLAY_P3;
+        default:
+            return COLORSPACE_UNKNOWN;
+    }
+}
+
 static status_t notifyMediaScanner(const char* fileName) {
     String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://");
     String8 fileUrl("\"");
@@ -139,6 +171,7 @@
 
     void const* base = NULL;
     uint32_t w, s, h, f;
+    android_dataspace d;
     size_t size = 0;
 
     // Maps orientations from DisplayInfo to ISurfaceComposer
@@ -177,13 +210,15 @@
         h = screenshot.getHeight();
         s = screenshot.getStride();
         f = screenshot.getFormat();
+        d = screenshot.getDataSpace();
         size = screenshot.getSize();
     }
 
     if (base != NULL) {
         if (png) {
             const SkImageInfo info =
-                SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType);
+                SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType,
+                    dataSpaceToColorSpace(d));
             SkPixmap pixmap(info, base, s * bytesPerPixel(f));
             struct FDWStream final : public SkWStream {
               size_t fBytesWritten = 0;
@@ -200,9 +235,11 @@
                 notifyMediaScanner(fn);
             }
         } else {
+            uint32_t c = dataSpaceToInt(d);
             write(fd, &w, 4);
             write(fd, &h, 4);
             write(fd, &f, 4);
+            write(fd, &c, 4);
             size_t Bpp = bytesPerPixel(f);
             for (size_t y=0 ; y<h ; y++) {
                 write(fd, base, w*Bpp);