hwc2: Add support for per frame layer metadata

Change-Id: Icd7093690954b30ce99e72119a740c6bfb636a7d
CRs-Fixed: 2237407
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 2619d75..c2a5cb4 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -885,6 +885,29 @@
   }
 }
 
+HWC2::Error HWCDisplay::GetPerFrameMetadataKeys(uint32_t *out_num_keys,
+                                                PerFrameMetadataKey *out_keys) {
+  if (out_num_keys == nullptr) {
+    return HWC2::Error::BadParameter;
+  }
+  *out_num_keys = UINT32(PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL) + 1;
+  if (out_keys != nullptr) {
+    out_keys[0] = PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X;
+    out_keys[1] = PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y;
+    out_keys[2] = PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X;
+    out_keys[3] = PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y;
+    out_keys[4] = PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X;
+    out_keys[5] = PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y;
+    out_keys[6] = PerFrameMetadataKey::WHITE_POINT_X;
+    out_keys[7] = PerFrameMetadataKey::WHITE_POINT_Y;
+    out_keys[8] = PerFrameMetadataKey::MAX_LUMINANCE;
+    out_keys[9] = PerFrameMetadataKey::MIN_LUMINANCE;
+    out_keys[10] = PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL;
+    out_keys[11] = PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL;
+  }
+  return HWC2::Error::None;
+}
+
 HWC2::Error HWCDisplay::GetActiveConfig(hwc2_config_t *out_config) {
   if (out_config == nullptr) {
     return HWC2::Error::BadDisplay;
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 3e4271d..b4bb554 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -255,6 +255,8 @@
                                          float* out_max_luminance,
                                          float* out_max_average_luminance,
                                          float* out_min_luminance);
+  virtual HWC2::Error GetPerFrameMetadataKeys(uint32_t *out_num_keys,
+                                              PerFrameMetadataKey *out_keys);
   virtual HWC2::Error SetDisplayAnimating(bool animating) {
     animating_ = animating;
     validated_ = false;
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 7aac16f..840119e 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -517,6 +517,56 @@
   return HWC2::Error::None;
 }
 
+HWC2::Error HWCLayer::SetLayerPerFrameMetadata(uint32_t num_elements,
+                                               const PerFrameMetadataKey *keys,
+                                               const float *metadata) {
+  auto &mastering_display = layer_->input_buffer.color_metadata.masteringDisplayInfo;
+  auto &content_light = layer_->input_buffer.color_metadata.contentLightLevel;
+  for (uint32_t i = 0; i < num_elements; i++) {
+    switch (keys[i]) {
+      case PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X:
+        mastering_display.colorVolumeSEIEnabled = true;
+        mastering_display.primaries.rgbPrimaries[0][0] = UINT32(metadata[i] * 50000);
+        break;
+      case PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y:
+        mastering_display.primaries.rgbPrimaries[0][1] = UINT32(metadata[i] * 50000);
+        break;
+      case PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X:
+        mastering_display.primaries.rgbPrimaries[1][0] = UINT32(metadata[i] * 50000);
+        break;
+      case PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y:
+        mastering_display.primaries.rgbPrimaries[1][1] = UINT32(metadata[i] * 50000);
+        break;
+      case PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X:
+        mastering_display.primaries.rgbPrimaries[2][0] = UINT32(metadata[i] * 50000);
+        break;
+      case PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y:
+        mastering_display.primaries.rgbPrimaries[2][1] = UINT32(metadata[i] * 50000);
+        break;
+      case PerFrameMetadataKey::WHITE_POINT_X:
+        mastering_display.primaries.whitePoint[0] = UINT32(metadata[i] * 50000);
+        break;
+      case PerFrameMetadataKey::WHITE_POINT_Y:
+        mastering_display.primaries.whitePoint[1] = UINT32(metadata[i] * 50000);
+        break;
+      case PerFrameMetadataKey::MAX_LUMINANCE:
+        mastering_display.maxDisplayLuminance = UINT32(metadata[i]);
+        break;
+      case PerFrameMetadataKey::MIN_LUMINANCE:
+        mastering_display.minDisplayLuminance = UINT32(metadata[i] * 10000);
+        break;
+      case PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL:
+        content_light.lightLevelSEIEnabled = true;
+        content_light.maxContentLightLevel = UINT32(metadata[i]);
+        break;
+      case PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL:
+        content_light.minPicAverageLightLevel = UINT32(metadata[i] * 10000);
+        break;
+    }
+  }
+  return HWC2::Error::None;
+}
+
 void HWCLayer::SetRect(const hwc_rect_t &source, LayerRect *target) {
   target->left = FLOAT(source.left);
   target->top = FLOAT(source.top);
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index 0b08bb5..d72f07f 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -32,12 +32,16 @@
 #include <hardware/hwcomposer2.h>
 #undef HWC2_INCLUDE_STRINGIFICATION
 #undef HWC2_USE_CPP11
-#include <map>
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
 #include <deque>
+#include <map>
 #include <set>
 #include "core/buffer_allocator.h"
 #include "hwc_buffer_allocator.h"
 
+using PerFrameMetadataKey =
+    android::hardware::graphics::composer::V2_2::IComposerClient::PerFrameMetadataKey;
+
 namespace sdm {
 
 DisplayError SetCSC(const private_handle_t *pvt_handle, ColorMetaData *color_metadata);
@@ -83,6 +87,8 @@
   HWC2::Error SetLayerSurfaceDamage(hwc_region_t damage);
   HWC2::Error SetLayerTransform(HWC2::Transform transform);
   HWC2::Error SetLayerVisibleRegion(hwc_region_t visible);
+  HWC2::Error SetLayerPerFrameMetadata(uint32_t num_elements, const PerFrameMetadataKey *keys,
+                                       const float *metadata);
   HWC2::Error SetLayerZOrder(uint32_t z);
   void SetComposition(const LayerComposition &sdm_composition);
   HWC2::Composition GetClientRequestedCompositionType() { return client_requested_; }
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index d9409a8..10482ae 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -509,6 +509,21 @@
   return HWC2_ERROR_NONE;
 }
 
+static int32_t GetPerFrameMetadataKeys(hwc2_device_t *device, hwc2_display_t display,
+                                       uint32_t *out_num_keys, int32_t *int_out_keys) {
+  auto out_keys = reinterpret_cast<PerFrameMetadataKey *>(int_out_keys);
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetPerFrameMetadataKeys,
+                                         out_num_keys, out_keys);
+}
+
+static int32_t SetLayerPerFrameMetadata(hwc2_device_t *device, hwc2_display_t display,
+                                        hwc2_layer_t layer, uint32_t num_elements,
+                                        const int32_t *int_keys, const float *metadata) {
+  auto keys = reinterpret_cast<const PerFrameMetadataKey *>(int_keys);
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPerFrameMetadata,
+                                       num_elements, keys, metadata);
+}
+
 static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
                                    hwc2_config_t config, int32_t int_attribute,
                                    int32_t *out_value) {
@@ -971,6 +986,10 @@
           HWCSession::SetColorModeWithRenderIntent);
     case HWC2::FunctionDescriptor::GetDataspaceSaturationMatrix:
       return AsFP<HWC2_PFN_GET_DATASPACE_SATURATION_MATRIX>(GetDataspaceSaturationMatrix);
+    case HWC2::FunctionDescriptor::GetPerFrameMetadataKeys:
+      return AsFP<HWC2_PFN_GET_PER_FRAME_METADATA_KEYS>(GetPerFrameMetadataKeys);
+    case HWC2::FunctionDescriptor::SetLayerPerFrameMetadata:
+      return AsFP<HWC2_PFN_SET_LAYER_PER_FRAME_METADATA>(SetLayerPerFrameMetadata);
     default:
       DLOGD("Unknown/Unimplemented function descriptor: %d (%s)", int_descriptor,
             to_string(descriptor).c_str());