sdm: Add support of SetLayerColorTransform with GL composition fallback

On legacy devices where per layer color transform is not supported, the
call of SetLayerColorTransform cannot fallback to GL composition
correctly because the error handling of the call in setPerFrameData
cannot receive the unsupported error immediately. The patch implemented
SetLayerColorTransform to trigger GL composition fallback.

Bug: 140917834
Test: PTS with SetLayerColorTransform
Change-Id: Ib41eb18d3c141714dbf6276b59b33f6d4d04f8a1
diff --git a/sdm/include/utils/constants.h b/sdm/include/utils/constants.h
index 5efe357..608b192 100644
--- a/sdm/include/utils/constants.h
+++ b/sdm/include/utils/constants.h
@@ -75,6 +75,12 @@
   const int kPageSize = 4096;
   const uint32_t kGridSize = 129;  // size used for non-linear transformation before Tone-mapping
   const uint32_t kLutDim = 17;  // Dim of the 3d LUT for tone-mapping.
+  constexpr int kColorTransformMatrixSize = 16;
+  constexpr float kIdentityMatrix[kColorTransformMatrixSize] = { 1.0, 0.0, 0.0, 0.0,
+                                                                 0.0, 1.0, 0.0, 0.0,
+                                                                 0.0, 0.0, 1.0, 0.0,
+                                                                 0.0, 0.0, 0.0, 1.0 };
+
 
   typedef void * Handle;
 
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 45effc0..18923b0 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -707,6 +707,10 @@
       layer->flags.skip = true;
     }
 
+    if (hwc_layer->IsColorTransformSet()) {
+      layer->flags.skip = true;
+    }
+
     // set default composition as GPU for SDM
     layer->composition = kCompositionGPU;
 
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 9b08308..eff1f80 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -536,6 +536,12 @@
   return HWC2::Error::None;
 }
 
+HWC2::Error HWCLayer::SetLayerColorTransform(const float *matrix) {
+  color_transform_matrix_set_ =
+      (std::memcmp(matrix, kIdentityMatrix, sizeof(kIdentityMatrix)) != 0);
+  return HWC2::Error::None;
+}
+
 HWC2::Error HWCLayer::SetLayerPerFrameMetadata(uint32_t num_elements,
                                                const PerFrameMetadataKey *keys,
                                                const float *metadata) {
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index a24f5a4..ce3bd1f 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -91,6 +91,7 @@
   HWC2::Error SetLayerPerFrameMetadata(uint32_t num_elements, const PerFrameMetadataKey *keys,
                                        const float *metadata);
   HWC2::Error SetLayerZOrder(uint32_t z);
+  HWC2::Error SetLayerColorTransform(const float *matrix);
   void SetComposition(const LayerComposition &sdm_composition);
   HWC2::Composition GetClientRequestedCompositionType() { return client_requested_; }
   void UpdateClientCompositionType(HWC2::Composition type) { client_requested_ = type; }
@@ -112,6 +113,7 @@
   bool IsNonIntegralSourceCrop() { return non_integral_source_crop_; }
   bool HasMetaDataRefreshRate() { return has_metadata_refresh_rate_; }
   void SetPartialUpdate(bool enabled) { partial_update_enabled_ = enabled; }
+  bool IsColorTransformSet() const { return color_transform_matrix_set_; }
 
  private:
   Layer *layer_ = nullptr;
@@ -131,6 +133,7 @@
   bool has_metadata_refresh_rate_ = false;
   bool partial_update_enabled_ = false;
   bool surface_updated_ = true;
+  bool color_transform_matrix_set_ = false;
 
   // 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 259c204..b35beb3 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -850,6 +850,12 @@
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
 }
 
+static int32_t SetLayerColorTransform(hwc2_device_t *device, hwc2_display_t display,
+                                      hwc2_layer_t layer, const float *matrix) {
+  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColorTransform,
+                                       matrix);
+}
+
 int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
                                     buffer_handle_t buffer, int32_t releaseFence) {
   if (!device) {
@@ -1112,6 +1118,8 @@
       return AsFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(SetLayerVisibleRegion);
     case HWC2::FunctionDescriptor::SetLayerZOrder:
       return AsFP<HWC2_PFN_SET_LAYER_Z_ORDER>(SetLayerZOrder);
+    case HWC2::FunctionDescriptor::SetLayerColorTransform:
+      return AsFP<HWC2_PFN_SET_LAYER_COLOR_TRANSFORM>(SetLayerColorTransform);
     case HWC2::FunctionDescriptor::SetOutputBuffer:
       return AsFP<HWC2_PFN_SET_OUTPUT_BUFFER>(SetOutputBuffer);
     case HWC2::FunctionDescriptor::SetPowerMode: