hwc2: Add support for HDR10PLUS

- Add support HDR10PLUS hdr capability.
- Add support for SetLayerPerFrameMetadataBlobs from composer 2.3.
- Populate the dynamic metadata from the new composer API into
  the layer structure and set validate if the data changes.
- Prioritize PerFrameMetadata/Blob over ColorMetaData.

Change-Id: Idd9b6f4f104d1584cce31a4cb7022e11eb2751ad
CRs-Fixed: 2545757
Signed-off-by: Karthi Kandasamy <kartka@codeaurora.org>
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index 0ec89da..306ff72 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -28,6 +28,7 @@
                                  android.hardware.graphics.allocator@2.0 \
                                  android.hardware.graphics.allocator@3.0 \
                                  android.hardware.graphics.composer@2.2 \
+                                 android.hardware.graphics.composer@2.3 \
                                  vendor.display.config@1.0 \
                                  vendor.display.config@1.1 \
                                  vendor.display.config@1.2 \
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 22b9f89..14ca3e6 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1111,20 +1111,14 @@
   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;
+  const uint32_t num_keys = UINT32(PerFrameMetadataKey::HDR10_PLUS_SEI) + 1;
+  if (out_keys == nullptr) {
+    *out_num_keys = num_keys;
+  } else {
+    uint32_t max_out_key_elements = std::min(*out_num_keys, num_keys);
+    for (int32_t i = 0; i < max_out_key_elements; i++) {
+      out_keys[i] = static_cast<PerFrameMetadataKey>(i);
+    }
   }
   return HWC2::Error::None;
 }
@@ -1474,12 +1468,13 @@
   }
 
   if (out_types == nullptr) {
-    // We support HDR10 and HLG
-    *out_num_types = 2;
+    // We support HDR10, HLG and HDR10_PLUS.
+    *out_num_types = 3;
   } else {
-    // HDR10 and HLG are supported
+    // HDR10, HLG and HDR10_PLUS are supported.
     out_types[0] = HAL_HDR_HDR10;
     out_types[1] = HAL_HDR_HLG;
+    out_types[2] = HAL_HDR_HDR10_PLUS;
     *out_max_luminance = fixed_info.max_luminance;
     *out_max_average_luminance = fixed_info.average_luminance;
     *out_min_luminance = fixed_info.min_luminance;
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index d8c8c4e..8bbd97e 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -551,6 +551,8 @@
 HWC2::Error HWCLayer::SetLayerPerFrameMetadata(uint32_t num_elements,
                                                const PerFrameMetadataKey *keys,
                                                const float *metadata) {
+  auto old_mastering_display = layer_->input_buffer.color_metadata.masteringDisplayInfo;
+  auto old_content_light = layer_->input_buffer.color_metadata.contentLightLevel;
   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++) {
@@ -593,6 +595,51 @@
       case PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL:
         content_light.minPicAverageLightLevel = UINT32(metadata[i] * 10000);
         break;
+      default:
+        break;
+    }
+  }
+  if ((!SameConfig(&old_mastering_display, &mastering_display, UINT32(sizeof(MasteringDisplay)))) ||
+       (!SameConfig(&old_content_light, &content_light, UINT32(sizeof(ContentLightLevel))))) {
+    per_frame_hdr_metadata_ = true;
+    layer_->update_mask.set(kMetadataUpdate);
+    geometry_changes_ |= kDataspace;
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerPerFrameMetadataBlobs(uint32_t num_elements,
+                                                    const PerFrameMetadataKey *keys,
+                                                    const uint32_t *sizes,
+                                                    const uint8_t* metadata) {
+  if (!keys || !sizes || !metadata) {
+    DLOGE("metadata or sizes or keys is null");
+    return HWC2::Error::BadParameter;
+  }
+
+  ColorMetaData &color_metadata = layer_->input_buffer.color_metadata;
+  for (uint32_t i = 0; i < num_elements; i++) {
+    switch (keys[i]) {
+      case PerFrameMetadataKey::HDR10_PLUS_SEI:
+        if (sizes[i] > HDR_DYNAMIC_META_DATA_SZ) {
+          DLOGE("Size of HDR10_PLUS_SEI = %d", sizes[i]);
+          return HWC2::Error::BadParameter;
+        }
+        per_frame_hdr_metadata_ = false;
+        // if dynamic metadata changes, store and set needs validate
+        if (!SameConfig(static_cast<const uint8_t*>(color_metadata.dynamicMetaDataPayload),
+                        metadata, sizes[i])) {
+          geometry_changes_ |= kDataspace;
+          color_metadata.dynamicMetaDataValid = true;
+          color_metadata.dynamicMetaDataLen = sizes[i];
+          std::memcpy(color_metadata.dynamicMetaDataPayload, metadata, sizes[i]);
+          per_frame_hdr_metadata_ = true;
+          layer_->update_mask.set(kMetadataUpdate);
+        }
+        break;
+      default:
+        DLOGW("Invalid key = %d", keys[i]);
+        return HWC2::Error::BadParameter;
     }
   }
   return HWC2::Error::None;
@@ -882,6 +929,11 @@
 }
 
 void HWCLayer::ValidateAndSetCSC(const private_handle_t *handle) {
+  if (per_frame_hdr_metadata_) {
+    // Since client has set PerFrameMetadata, dataspace will be valid
+    // so we can skip reading from ColorMetaData.
+    return;
+  }
   LayerBuffer *layer_buffer = &layer_->input_buffer;
   bool use_color_metadata = true;
   ColorMetaData csc = {};
@@ -920,6 +972,9 @@
           (layer_buffer->color_metadata.range != old_meta_data.range)) {
         layer_->update_mask.set(kMetadataUpdate);
       }
+      DLOGV_IF(kTagClient, "Dynamic Metadata valid = %d size = %d",
+               layer_buffer->color_metadata.dynamicMetaDataValid,
+               layer_buffer->color_metadata.dynamicMetaDataLen);
       if (layer_buffer->color_metadata.dynamicMetaDataValid &&
           !SameConfig(layer_buffer->color_metadata.dynamicMetaDataPayload,
           old_meta_data.dynamicMetaDataPayload, HDR_DYNAMIC_META_DATA_SZ)) {
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index 10d7156..76b7c14 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -33,7 +33,7 @@
 #include <hardware/hwcomposer2.h>
 #undef HWC2_INCLUDE_STRINGIFICATION
 #undef HWC2_USE_CPP11
-#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
 #include <deque>
 #include <map>
 #include <set>
@@ -41,7 +41,7 @@
 #include "hwc_buffer_allocator.h"
 
 using PerFrameMetadataKey =
-    android::hardware::graphics::composer::V2_2::IComposerClient::PerFrameMetadataKey;
+    android::hardware::graphics::composer::V2_3::IComposerClient::PerFrameMetadataKey;
 
 namespace sdm {
 
@@ -91,6 +91,8 @@
   HWC2::Error SetLayerVisibleRegion(hwc_region_t visible);
   HWC2::Error SetLayerPerFrameMetadata(uint32_t num_elements, const PerFrameMetadataKey *keys,
                                        const float *metadata);
+  HWC2::Error SetLayerPerFrameMetadataBlobs(uint32_t num_elements, const PerFrameMetadataKey *keys,
+                                            const uint32_t *sizes, const uint8_t* metadata);
   HWC2::Error SetLayerZOrder(uint32_t z);
   void SetComposition(const LayerComposition &sdm_composition);
   HWC2::Composition GetClientRequestedCompositionType() { return client_requested_; }
@@ -136,6 +138,7 @@
   bool non_integral_source_crop_ = false;
   bool has_metadata_refresh_rate_ = false;
   bool buffer_flipped_ = false;
+  bool per_frame_hdr_metadata_ = false;  // used to track if perframe metadata and blob is set.
 
   // Composition requested by client(SF)
   HWC2::Composition client_requested_ = HWC2::Composition::Device;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 7a8c4e2..8663705 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -677,6 +677,16 @@
                                        num_elements, keys, metadata);
 }
 
+static int32_t SetLayerPerFrameMetadataBlobs(hwc2_device_t *device, hwc2_display_t display,
+                                             hwc2_layer_t layer, uint32_t num_elements,
+                                             const int32_t *int_keys, const uint32_t *sizes,
+                                             const uint8_t *metadata) {
+  auto keys = reinterpret_cast<const PerFrameMetadataKey *>(int_keys);
+  return HWCSession::CallLayerFunction(device, display, layer,
+                                       &HWCLayer::SetLayerPerFrameMetadataBlobs,
+                                       num_elements, keys, sizes, 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) {
@@ -1290,6 +1300,8 @@
       return AsFP<HWC2_PFN_GET_PER_FRAME_METADATA_KEYS>(GetPerFrameMetadataKeys);
     case HWC2::FunctionDescriptor::SetLayerPerFrameMetadata:
       return AsFP<HWC2_PFN_SET_LAYER_PER_FRAME_METADATA>(SetLayerPerFrameMetadata);
+    case HWC2::FunctionDescriptor::SetLayerPerFrameMetadataBlobs:
+      return AsFP<HWC2_PFN_SET_LAYER_PER_FRAME_METADATA_BLOBS>(SetLayerPerFrameMetadataBlobs);
     case HWC2::FunctionDescriptor::GetDisplayIdentificationData:
       return AsFP<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>
              (HWCSession::GetDisplayIdentificationData);