drm_hwcomposer: Add support for color encoding and range properties

Starting from the linux-v4.17, the DRM module has support for different
non-RGB color encodings that are controlled through plane-specific
COLOR_ENCODING and COLOR_RANGE properties.

This patch creates a matching between the HWC layer dataspace which is
supported by DRM driver and DRM plane properties.

Signed-off-by: Matvii Zorin <matvii.zorin@globallogic.com>
diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp
index ba0d56b..3ae42ef 100644
--- a/compositor/DrmDisplayCompositor.cpp
+++ b/compositor/DrmDisplayCompositor.cpp
@@ -342,6 +342,8 @@
     uint64_t rotation = 0;
     uint64_t alpha = 0xFFFF;
     uint64_t blend;
+    uint64_t color_encoding = UINT64_MAX;
+    uint64_t color_range = UINT64_MAX;
 
     if (comp_plane.type() != DrmCompositionPlane::Type::kDisable) {
       if (source_layers.size() > 1) {
@@ -427,6 +429,45 @@
           break;
         }
       }
+
+      if (plane->color_encoding_propery().id()) {
+        switch (layer.dataspace & HAL_DATASPACE_STANDARD_MASK) {
+          case HAL_DATASPACE_STANDARD_BT709:
+            std::tie(color_encoding,
+                     ret) = plane->color_encoding_propery()
+                                .GetEnumValueWithName("ITU-R BT.709 YCbCr");
+            break;
+          case HAL_DATASPACE_STANDARD_BT601_625:
+          case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+          case HAL_DATASPACE_STANDARD_BT601_525:
+          case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+            std::tie(color_encoding,
+                     ret) = plane->color_encoding_propery()
+                                .GetEnumValueWithName("ITU-R BT.601 YCbCr");
+            break;
+          case HAL_DATASPACE_STANDARD_BT2020:
+          case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
+            std::tie(color_encoding,
+                     ret) = plane->color_encoding_propery()
+                                .GetEnumValueWithName("ITU-R BT.2020 YCbCr");
+            break;
+        }
+      }
+
+      if (plane->color_range_property().id()) {
+        switch (layer.dataspace & HAL_DATASPACE_RANGE_MASK) {
+          case HAL_DATASPACE_RANGE_FULL:
+            std::tie(color_range,
+                     ret) = plane->color_range_property()
+                                .GetEnumValueWithName("YCbCr full range");
+            break;
+          case HAL_DATASPACE_RANGE_LIMITED:
+            std::tie(color_range,
+                     ret) = plane->color_range_property()
+                                .GetEnumValueWithName("YCbCr limited range");
+            break;
+        }
+      }
     }
 
     // Disable the plane if there's no framebuffer
@@ -509,6 +550,28 @@
         break;
       }
     }
+
+    if (plane->color_encoding_propery().id() && color_encoding != UINT64_MAX) {
+      ret = drmModeAtomicAddProperty(pset, plane->id(),
+                                     plane->color_encoding_propery().id(),
+                                     color_encoding) < 0;
+      if (ret) {
+        ALOGE("Failed to add COLOR_ENCODING property %d to plane %d",
+              plane->color_encoding_propery().id(), plane->id());
+        break;
+      }
+    }
+
+    if (plane->color_range_property().id() && color_range != UINT64_MAX) {
+      ret = drmModeAtomicAddProperty(pset, plane->id(),
+                                     plane->color_range_property().id(),
+                                     color_range) < 0;
+      if (ret) {
+        ALOGE("Failed to add COLOR_RANGE property %d to plane %d",
+              plane->color_range_property().id(), plane->id());
+        break;
+      }
+    }
   }
 
   if (!ret) {