sdm: hwc2: Plumb render intent APIs

* Add support for color mode with render intents.
* Remove transform hints as they are unused.
* Add saturation matrix, read from a property by default.

Change-Id: Ic8526854cbdcb8f6fe1f2b2b260b3999a5c4571a
CRs-Fixed: 2235178
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index e9511f7..d9ffa0b 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -24,7 +24,8 @@
                                  vendor.display.config@1.0 \
                                  android.hardware.graphics.mapper@2.0 \
                                  android.hardware.graphics.mapper@2.1 \
-                                 android.hardware.graphics.allocator@2.0
+                                 android.hardware.graphics.allocator@2.0 \
+                                 android.hardware.graphics.composer@2.2 \
 
 ifeq ($(display_config_version), DISPLAY_CONFIG_1_1)
 LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 2cc97cb..7cb8e72 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -67,47 +67,73 @@
 }
 
 HWC2::Error HWCColorMode::DeInit() {
-  color_mode_transform_map_.clear();
+  color_mode_map_.clear();
   return HWC2::Error::None;
 }
 
 uint32_t HWCColorMode::GetColorModeCount() {
-  uint32_t count = UINT32(color_mode_transform_map_.size());
+  uint32_t count = UINT32(color_mode_map_.size());
   DLOGI("Supported color mode count = %d", count);
-
   return std::max(1U, count);
 }
 
-HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes,
-                                        android_color_mode_t *out_modes) {
-  auto it = color_mode_transform_map_.begin();
-  *out_num_modes = std::min(*out_num_modes, UINT32(color_mode_transform_map_.size()));
+uint32_t HWCColorMode::GetRenderIntentCount(ColorMode mode) {
+  uint32_t count = UINT32(color_mode_map_[mode].size());
+  DLOGI("mode: %d supported rendering intent count = %d", mode, count);
+  return std::max(1U, count);
+}
+
+HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
+  auto it = color_mode_map_.begin();
+  *out_num_modes = std::min(*out_num_modes, UINT32(color_mode_map_.size()));
   for (uint32_t i = 0; i < *out_num_modes; it++, i++) {
     out_modes[i] = it->first;
-    DLOGI("Supports color mode[%d] = %d", i, it->first);
+    DLOGI("Color mode = %d is supported", out_modes[i]);
   }
-
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCColorMode::SetColorMode(android_color_mode_t mode) {
+HWC2::Error HWCColorMode::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
+                                           RenderIntent *out_intents) {
+  if (color_mode_map_.find(mode) == color_mode_map_.end()) {
+    return HWC2::Error::BadParameter;
+  }
+  auto it = color_mode_map_[mode].begin();
+  *out_num_intents = std::min(*out_num_intents, UINT32(color_mode_map_[mode].size()));
+  for (uint32_t i = 0; i < *out_num_intents; it++, i++) {
+    out_intents[i] = it->first;
+    DLOGI("Color mode = %d is supported with render intent = %d", mode, out_intents[i]);
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMode::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
   DTRACE_SCOPED();
-  // first mode in 2D matrix is the mode (identity)
-  if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_DISPLAY_P3) {
+  if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
     DLOGE("Could not find mode: %d", mode);
     return HWC2::Error::BadParameter;
   }
-  if (color_mode_transform_map_.find(mode) == color_mode_transform_map_.end()) {
+  if (color_mode_map_.find(mode) == color_mode_map_.end()) {
+    return HWC2::Error::Unsupported;
+  }
+  if (color_mode_map_[mode].find(intent) == color_mode_map_[mode].end()) {
     return HWC2::Error::Unsupported;
   }
 
-  auto status = HandleColorModeTransform(mode, current_color_transform_, color_matrix_);
-  if (status != HWC2::Error::None) {
-    DLOGE("failed for mode = %d", mode);
+  auto mode_string = color_mode_map_[mode][intent];
+  DisplayError error = display_intf_->SetColorMode(mode_string);
+  if (error != kErrorNone) {
+    DLOGE("failed for mode = %d intent = %d name = %s", mode, intent, mode_string.c_str());
+    return HWC2::Error::Unsupported;
   }
+  // The mode does not have the PCC configured, restore the transform
+  RestoreColorTransform();
 
-  DLOGV_IF(kTagClient, "Color mode %d successfully set.", mode);
-  return status;
+  current_color_mode_ = mode;
+  current_render_intent_ = intent;
+  DLOGV_IF(kTagClient, "Successfully applied mode = %d intent = %d name = %s", mode, intent,
+           mode_string.c_str());
+  return HWC2::Error::None;
 }
 
 HWC2::Error HWCColorMode::SetColorModeById(int32_t color_mode_id) {
@@ -130,80 +156,42 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCColorMode::SetColorTransform(const float *matrix, android_color_transform_t hint) {
+HWC2::Error HWCColorMode::SetColorTransform(const float *matrix,
+                                            android_color_transform_t /*hint*/) {
   DTRACE_SCOPED();
+  auto status = HWC2::Error::None;
   double color_matrix[kColorTransformMatrixCount] = {0};
   CopyColorTransformMatrix(matrix, color_matrix);
 
-  auto status = HandleColorModeTransform(current_color_mode_, hint, color_matrix);
-  if (status != HWC2::Error::None) {
-    DLOGE("failed for hint = %d", hint);
+  DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix);
+  if (error != kErrorNone) {
+    DLOGE("Failed to set Color Transform Matrix");
+    status = HWC2::Error::Unsupported;
   }
-
+  CopyColorTransformMatrix(matrix, color_matrix_);
   return status;
 }
 
-HWC2::Error HWCColorMode::HandleColorModeTransform(android_color_mode_t mode,
-                                                   android_color_transform_t hint,
-                                                   const double *matrix) {
-  android_color_transform_t transform_hint = hint;
-  std::string color_mode_transform;
-  bool use_matrix = false;
-  if (hint != HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX) {
-    // if the mode + transfrom request from HWC matches one mode in SDM, set that
-    if (color_mode_transform.empty()) {
-      transform_hint = HAL_COLOR_TRANSFORM_IDENTITY;
-      use_matrix = true;
-    } else {
-      color_mode_transform = color_mode_transform_map_[mode][hint];
-    }
-  } else {
-    use_matrix = true;
-    transform_hint = HAL_COLOR_TRANSFORM_IDENTITY;
+void HWCColorMode::FindRenderIntent(const ColorMode &mode, const std::string &mode_string) {
+  auto intent = RenderIntent::COLORIMETRIC;
+  if (mode_string.find("enhanced") != std::string::npos) {
+    intent = RenderIntent::ENHANCE;
   }
-
-  // if the mode count is 1, then only native mode is supported, so just apply matrix w/o
-  // setting mode
-  if (color_mode_transform_map_.size() > 1U && current_color_mode_ != mode) {
-    color_mode_transform = color_mode_transform_map_[mode][transform_hint];
-    DisplayError error = display_intf_->SetColorMode(color_mode_transform);
-    if (error != kErrorNone) {
-      DLOGE("Failed to set color_mode  = %d transform_hint = %d", mode, hint);
-      // failure to force client composition
-      return HWC2::Error::Unsupported;
-    }
-    DLOGI("Setting Color Mode = %d Transform Hint = %d Success", mode, hint);
-  }
-
-  if (use_matrix) {
-    DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, matrix);
-    if (error != kErrorNone) {
-      DLOGE("Failed to set Color Transform Matrix");
-      // failure to force client composition
-      return HWC2::Error::Unsupported;
-    }
-  }
-
-  current_color_mode_ = mode;
-  current_color_transform_ = hint;
-  CopyColorTransformMatrix(matrix, color_matrix_);
-
-  return HWC2::Error::None;
+  color_mode_map_[mode][intent] = mode_string;
 }
 
 void HWCColorMode::PopulateColorModes() {
   uint32_t color_mode_count = 0;
-  // SDM returns modes which is string combination of mode + transform.
+  // SDM returns modes which have attributes defining mode and rendering intent
   DisplayError error = display_intf_->GetColorModeCount(&color_mode_count);
   if (error != kErrorNone || (color_mode_count == 0)) {
     DLOGW("GetColorModeCount failed, use native color mode");
-    PopulateTransform(HAL_COLOR_MODE_NATIVE, "native", "identity");
+    color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC] = "hal_native_identity";
     return;
   }
 
   DLOGV_IF(kTagClient, "Color Modes supported count = %d", color_mode_count);
 
-  const std::string color_transform = "identity";
   std::vector<std::string> color_modes(color_mode_count);
   error = display_intf_->GetColorModes(&color_mode_count, &color_modes);
   for (uint32_t i = 0; i < color_mode_count; i++) {
@@ -211,7 +199,7 @@
     DLOGV_IF(kTagClient, "Color Mode[%d] = %s", i, mode_string.c_str());
     AttrVal attr;
     error = display_intf_->GetColorModeAttr(mode_string, &attr);
-    std::string color_gamut, dynamic_range, pic_quality;
+    std::string color_gamut = kNative, dynamic_range = kSdr, pic_quality = kStandard;
     if (!attr.empty()) {
       for (auto &it : attr) {
         if (it.first.find(kColorGamutAttribute) != std::string::npos) {
@@ -225,76 +213,52 @@
 
       DLOGV_IF(kTagClient, "color_gamut : %s, dynamic_range : %s, pic_quality : %s",
                color_gamut.c_str(), dynamic_range.c_str(), pic_quality.c_str());
-
-      if (dynamic_range == kHdr) {
-        continue;
+      if (color_gamut == kNative) {
+        color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC] = mode_string;
       }
-      if ((color_gamut == kNative) &&
-          (pic_quality.empty() || pic_quality == kStandard)) {
-        PopulateTransform(HAL_COLOR_MODE_NATIVE, mode_string, color_transform);
-      } else if ((color_gamut == kSrgb) &&
-                 (pic_quality.empty() || pic_quality == kStandard)) {
-        PopulateTransform(HAL_COLOR_MODE_SRGB, mode_string, color_transform);
-      } else if ((color_gamut == kDcip3) &&
-                 (pic_quality.empty() || pic_quality == kStandard)) {
-        PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, color_transform);
-      } else if ((color_gamut == kDisplayP3) &&
-                 (pic_quality.empty() || pic_quality == kStandard)) {
-        PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, color_transform);
-      }
-    }
 
-    // Look at the mode name, if no color gamut is found
-    if (color_gamut.empty()) {
+      if (color_gamut == kSrgb && dynamic_range == kSdr) {
+        if (pic_quality == kStandard) {
+          color_mode_map_[ColorMode::SRGB][RenderIntent::COLORIMETRIC] = mode_string;
+        }
+        if (pic_quality == kEnhanced) {
+          color_mode_map_[ColorMode::SRGB][RenderIntent::ENHANCE] = mode_string;
+        }
+      }
+
+      if (color_gamut == kDcip3 && dynamic_range == kSdr) {
+        if (pic_quality == kStandard) {
+          color_mode_map_[ColorMode::DISPLAY_P3][RenderIntent::COLORIMETRIC] = mode_string;
+        }
+        if (pic_quality == kEnhanced) {
+          color_mode_map_[ColorMode::DISPLAY_P3][RenderIntent::ENHANCE] = mode_string;
+        }
+      }
+
+      if (pic_quality == kStandard && dynamic_range == kHdr) {
+        color_mode_map_[ColorMode::BT2100_PQ][RenderIntent::TONE_MAP_COLORIMETRIC] = mode_string;
+        color_mode_map_[ColorMode::BT2100_HLG][RenderIntent::TONE_MAP_COLORIMETRIC] = mode_string;
+      }
+    } else {
+      // Look at the mode names, if no attributes are found
       if (mode_string.find("hal_native") != std::string::npos) {
-        PopulateTransform(HAL_COLOR_MODE_NATIVE, mode_string, mode_string);
-      } else if (mode_string.find("hal_srgb") != std::string::npos) {
-        PopulateTransform(HAL_COLOR_MODE_SRGB, mode_string, mode_string);
-      } else if (mode_string.find("hal_adobe") != std::string::npos) {
-        PopulateTransform(HAL_COLOR_MODE_ADOBE_RGB, mode_string, mode_string);
-      } else if (mode_string.find("hal_dci_p3") != std::string::npos) {
-        PopulateTransform(HAL_COLOR_MODE_DCI_P3, mode_string, mode_string);
-      } else if (mode_string.find("hal_display_p3") != std::string::npos) {
-        PopulateTransform(HAL_COLOR_MODE_DISPLAY_P3, mode_string, mode_string);
+        color_mode_map_[ColorMode::NATIVE][RenderIntent::COLORIMETRIC] = mode_string;
       }
     }
   }
 }
 
-void HWCColorMode::PopulateTransform(const android_color_mode_t &mode,
-                                     const std::string &color_mode,
-                                     const std::string &color_transform) {
-  // TODO(user): Check the substring from QDCM
-  if (color_transform.find("identity") != std::string::npos) {
-    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_IDENTITY] = color_mode;
-  } else if (color_transform.find("arbitrary") != std::string::npos) {
-    // no color mode for arbitrary
-  } else if (color_transform.find("inverse") != std::string::npos) {
-    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_VALUE_INVERSE] = color_mode;
-  } else if (color_transform.find("grayscale") != std::string::npos) {
-    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_GRAYSCALE] = color_mode;
-  } else if (color_transform.find("correct_protonopia") != std::string::npos) {
-    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA] = color_mode;
-  } else if (color_transform.find("correct_deuteranopia") != std::string::npos) {
-    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA] = color_mode;
-  } else if (color_transform.find("correct_tritanopia") != std::string::npos) {
-    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA] = color_mode;
-  } else {
-    color_mode_transform_map_[mode][HAL_COLOR_TRANSFORM_IDENTITY] = color_mode;
-  }
-}
-
 HWC2::Error HWCColorMode::ApplyDefaultColorMode() {
-  android_color_mode_t color_mode = HAL_COLOR_MODE_NATIVE;
-  if (color_mode_transform_map_.size() == 1U) {
-    color_mode = color_mode_transform_map_.begin()->first;
-  } else if (color_mode_transform_map_.size() > 1U) {
+  auto color_mode = ColorMode::NATIVE;
+  if (color_mode_map_.size() == 1U) {
+    color_mode = color_mode_map_.begin()->first;
+  } else if (color_mode_map_.size() > 1U) {
     std::string default_color_mode;
     bool found = false;
     DisplayError error = display_intf_->GetDefaultColorMode(&default_color_mode);
     if (error == kErrorNone) {
       // get the default mode corresponding android_color_mode_t
-      for (auto &it_mode : color_mode_transform_map_) {
+      for (auto &it_mode : color_mode_map_) {
         for (auto &it : it_mode.second) {
           if (it.second == default_color_mode) {
             found = true;
@@ -308,20 +272,25 @@
       }
     }
 
-    // return the first andrid_color_mode_t when we encouter if not found
+    // return the first color mode we encounter if not found
     if (!found) {
-      color_mode = color_mode_transform_map_.begin()->first;
+      color_mode = color_mode_map_.begin()->first;
     }
   }
-  return SetColorMode(color_mode);
+  return SetColorModeWithRenderIntent(color_mode, RenderIntent::COLORIMETRIC);
 }
 
 void HWCColorMode::Dump(std::ostringstream* os) {
-  *os << "color modes supported: ";
-  for (auto it : color_mode_transform_map_) {
-    *os << it.first <<" ";
+  *os << "color modes supported: \n";
+  for (auto it : color_mode_map_) {
+    *os << "mode: " << static_cast<int32_t>(it.first) << " RIs { ";
+    for (auto rit : color_mode_map_[it.first]) {
+      *os << static_cast<int32_t>(rit.first) << " ";
+    }
+    *os << "} \n";
   }
-  *os << "current mode: " << current_color_mode_ << std::endl;
+  *os << "current mode: " << static_cast<uint32_t>(current_color_mode_) << std::endl;
+  *os << "current render_intent: " << static_cast<uint32_t>(current_render_intent_) << std::endl;
   *os << "current transform: ";
   for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
     if (i % 4 == 0) {
@@ -778,14 +747,27 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes) {
+HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
   if (out_modes == nullptr) {
     *out_num_modes = 1;
   } else if (out_modes && *out_num_modes > 0) {
     *out_num_modes = 1;
-    out_modes[0] = HAL_COLOR_MODE_NATIVE;
+    out_modes[0] = ColorMode::NATIVE;
   }
+  return HWC2::Error::None;
+}
 
+HWC2::Error HWCDisplay::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
+                                         RenderIntent *out_intents) {
+  if (mode != ColorMode::NATIVE) {
+    return HWC2::Error::Unsupported;
+  }
+  if (out_intents == nullptr) {
+    *out_num_intents = 1;
+  } else if (out_intents && *out_num_intents > 0) {
+    *out_num_intents = 1;
+    out_intents[0] = RenderIntent::COLORIMETRIC;
+  }
   return HWC2::Error::None;
 }
 
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index d35ea23..dc7d7b7 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -20,12 +20,13 @@
 #ifndef __HWC_DISPLAY_H__
 #define __HWC_DISPLAY_H__
 
-#include <sys/stat.h>
 #include <QService.h>
+#include <android/hardware/graphics/common/1.1/types.h>
 #include <core/core_interface.h>
 #include <hardware/hwcomposer.h>
 #include <private/color_params.h>
 #include <qdMetaData.h>
+#include <sys/stat.h>
 #include <map>
 #include <queue>
 #include <set>
@@ -40,6 +41,10 @@
 #include "display_null.h"
 #include "hwc_display_event_handler.h"
 
+using android::hardware::graphics::common::V1_1::ColorMode;
+using android::hardware::graphics::common::V1_1::Dataspace;
+using android::hardware::graphics::common::V1_1::RenderIntent;
+
 namespace sdm {
 
 class BlitEngine;
@@ -68,20 +73,18 @@
   HWC2::Error DeInit();
   void Dump(std::ostringstream* os);
   uint32_t GetColorModeCount();
-  HWC2::Error GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes);
-  HWC2::Error SetColorMode(android_color_mode_t mode);
+  uint32_t GetRenderIntentCount(ColorMode mode);
+  HWC2::Error GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes);
+  HWC2::Error GetRenderIntents(ColorMode mode, uint32_t *out_num_intents, RenderIntent *out_modes);
+  HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
   HWC2::Error SetColorModeById(int32_t color_mode_id);
   HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
   HWC2::Error RestoreColorTransform();
 
  private:
   static const uint32_t kColorTransformMatrixCount = 16;
-
-  HWC2::Error HandleColorModeTransform(android_color_mode_t mode,
-                                       android_color_transform_t hint, const double *matrix);
   void PopulateColorModes();
-  void PopulateTransform(const android_color_mode_t &mode,
-                         const std::string &color_mode, const std::string &color_transform);
+  void FindRenderIntent(const ColorMode &mode, const std::string &mode_string);
   template <class T>
   void CopyColorTransformMatrix(const T *input_matrix, double *output_matrix) {
     for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
@@ -91,10 +94,12 @@
   HWC2::Error ApplyDefaultColorMode();
 
   DisplayInterface *display_intf_ = NULL;
-  android_color_mode_t current_color_mode_ = HAL_COLOR_MODE_NATIVE;
-  android_color_transform_t current_color_transform_ = HAL_COLOR_TRANSFORM_IDENTITY;
-  typedef std::map<android_color_transform_t, std::string> TransformMap;
-  std::map<android_color_mode_t, TransformMap> color_mode_transform_map_ = {};
+
+  ColorMode current_color_mode_ = ColorMode::NATIVE;
+  RenderIntent current_render_intent_ = RenderIntent::COLORIMETRIC;
+  typedef std::map<RenderIntent, std::string> RenderIntentMap;
+  // Initialize supported mode/render intent combination
+  std::map<ColorMode, RenderIntentMap> color_mode_map_ = {};
   double color_matrix_[kColorTransformMatrixCount] = { 1.0, 0.0, 0.0, 0.0, \
                                                        0.0, 1.0, 0.0, 0.0, \
                                                        0.0, 0.0, 1.0, 0.0, \
@@ -203,7 +208,8 @@
   virtual HWC2::Error SetActiveConfig(hwc2_config_t config);
   virtual HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
                                       int32_t dataspace, hwc_region_t damage);
-  virtual HWC2::Error SetColorMode(android_color_mode_t mode) {
+  virtual HWC2::Error SetColorMode(ColorMode mode) { return HWC2::Error::Unsupported; }
+  virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
     return HWC2::Error::Unsupported;
   }
   virtual HWC2::Error SetColorModeById(int32_t color_mode_id) {
@@ -225,7 +231,9 @@
                                           int32_t *out_value);
   virtual HWC2::Error GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format,
                                              int32_t dataspace);
-  virtual HWC2::Error GetColorModes(uint32_t *outNumModes, android_color_mode_t *outModes);
+  virtual HWC2::Error GetColorModes(uint32_t *outNumModes, ColorMode *outModes);
+  virtual HWC2::Error GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
+                                       RenderIntent *out_intents);
   virtual HWC2::Error GetChangedCompositionTypes(uint32_t *out_num_elements,
                                                  hwc2_layer_t *out_layers, int32_t *out_types);
   virtual HWC2::Error GetDisplayRequests(int32_t *out_display_requests, uint32_t *out_num_elements,
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 36050d2..e285c04 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -250,8 +250,7 @@
   return status;
 }
 
-HWC2::Error HWCDisplayPrimary::GetColorModes(uint32_t *out_num_modes,
-                                             android_color_mode_t *out_modes) {
+HWC2::Error HWCDisplayPrimary::GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes) {
   if (out_modes == nullptr) {
     *out_num_modes = color_mode_->GetColorModeCount();
   } else {
@@ -261,16 +260,28 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCDisplayPrimary::SetColorMode(android_color_mode_t mode) {
-  auto status = color_mode_->SetColorMode(mode);
+HWC2::Error HWCDisplayPrimary::GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
+                                                RenderIntent *out_intents) {
+  if (out_intents == nullptr) {
+    *out_num_intents = color_mode_->GetRenderIntentCount(mode);
+  } else {
+    color_mode_->GetRenderIntents(mode, out_num_intents, out_intents);
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplayPrimary::SetColorMode(ColorMode mode) {
+  return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
+}
+
+HWC2::Error HWCDisplayPrimary::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
+  auto status = color_mode_->SetColorModeWithRenderIntent(mode, intent);
   if (status != HWC2::Error::None) {
-    DLOGE("failed for mode = %d", mode);
+    DLOGE("failed for mode = %d intent = %d", mode, intent);
     return status;
   }
-
   callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
   validated_ = false;
-
   return status;
 }
 
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h
index c561f4c..8957855 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -55,8 +55,11 @@
   virtual int Init();
   virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
   virtual HWC2::Error Present(int32_t *out_retire_fence);
-  virtual HWC2::Error GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes);
-  virtual HWC2::Error SetColorMode(android_color_mode_t mode);
+  virtual HWC2::Error GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes);
+  virtual HWC2::Error SetColorMode(ColorMode mode);
+  virtual HWC2::Error GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
+                                       RenderIntent *out_intents);
+  virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
   virtual HWC2::Error SetColorModeById(int32_t color_mode_id);
   virtual HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
   virtual HWC2::Error RestoreColorTransform();
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 237343f..d9409a8 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -17,26 +17,27 @@
  * limitations under the License.
  */
 
-#include <core/buffer_allocator.h>
-#include <private/color_params.h>
-#include <utils/constants.h>
-#include <utils/String16.h>
-#include <cutils/properties.h>
-#include <hardware_legacy/uevent.h>
-#include <sys/resource.h>
-#include <sys/prctl.h>
-#include <binder/Parcel.h>
 #include <QService.h>
+#include <binder/Parcel.h>
+#include <core/buffer_allocator.h>
+#include <cutils/properties.h>
 #include <display_config.h>
-#include <utils/debug.h>
-#include <sync/sync.h>
+#include <hardware_legacy/uevent.h>
+#include <private/color_params.h>
 #include <qd_utils.h>
+#include <sync/sync.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <utils/String16.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
 #include <utils/utils.h>
 #include <algorithm>
-#include <string>
 #include <bitset>
-#include <thread>
 #include <memory>
+#include <string>
+#include <thread>
+#include <vector>
 
 #include "hwc_buffer_allocator.h"
 #include "hwc_buffer_sync_handler.h"
@@ -440,8 +441,8 @@
 }
 
 static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes,
-                             int32_t /*android_color_mode_t*/ *int_out_modes) {
-  auto out_modes = reinterpret_cast<android_color_mode_t *>(int_out_modes);
+                             int32_t /*ColorMode*/ *int_out_modes) {
+  auto out_modes = reinterpret_cast<ColorMode *>(int_out_modes);
   if (out_num_modes == nullptr) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
@@ -449,6 +450,65 @@
                                          out_modes);
 }
 
+static int32_t GetRenderIntents(hwc2_device_t *device, hwc2_display_t display,
+                                int32_t /*ColorMode*/ int_mode, uint32_t *out_num_intents,
+                                int32_t /*RenderIntent*/ *int_out_intents) {
+  auto mode = static_cast<ColorMode>(int_mode);
+  auto out_intents = reinterpret_cast<RenderIntent *>(int_out_intents);
+  if (out_num_intents == nullptr) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetRenderIntents, mode,
+                                         out_num_intents, out_intents);
+}
+
+static int32_t GetDataspaceSaturationMatrix(hwc2_device_t *device,
+                                            int32_t /*Dataspace*/ int_dataspace,
+                                            float *out_matrix) {
+  auto dataspace = static_cast<Dataspace>(int_dataspace);
+  if (device == nullptr || out_matrix == nullptr || dataspace != Dataspace::SRGB_LINEAR) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+  // We only have the matrix for sRGB
+  float saturation_matrix[kDataspaceSaturationMatrixCount] = { 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 };
+
+  // TODO(user): This value should ideally be retrieved from a QDCM configuration file
+  char value[kPropertyMax] = {};
+  if (Debug::Get()->GetProperty(DATASPACE_SATURATION_MATRIX_PROP, value) != kErrorNone) {
+    DLOGW("Undefined saturation matrix");
+    return HWC2_ERROR_BAD_CONFIG;
+  }
+  std::string value_string(value);
+  std::size_t start = 0, end = 0;
+  int index = 0;
+  while ((end = value_string.find(",", start)) != std::string::npos) {
+    saturation_matrix[index] = std::stof(value_string.substr(start, end - start));
+    start = end + 1;
+    index++;
+    // We expect a 3x3, SF needs 4x4, keep the last row/column identity
+    if ((index + 1) % 4 == 0) {
+      index++;
+    }
+  }
+  saturation_matrix[index] = std::stof(value_string.substr(start, end - start));
+  if (index < kDataspaceSaturationPropertyElements - 1) {
+    // The property must have kDataspaceSaturationPropertyElements delimited by commas
+    DLOGW("Invalid saturation matrix defined");
+    return HWC2_ERROR_BAD_CONFIG;
+  }
+  for (int32_t i = 0; i < kDataspaceSaturationMatrixCount; i += 4) {
+    DLOGD("%f %f %f %f", saturation_matrix[i], saturation_matrix[i + 1], saturation_matrix[i + 2],
+          saturation_matrix[i + 3]);
+  }
+  for (uint32_t i = 0; i < kDataspaceSaturationMatrixCount; i++) {
+    out_matrix[i] = saturation_matrix[i];
+  }
+  return HWC2_ERROR_NONE;
+}
+
 static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
                                    hwc2_config_t config, int32_t int_attribute,
                                    int32_t *out_value) {
@@ -598,14 +658,26 @@
 }
 
 int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display,
-                                 int32_t /*android_color_mode_t*/ int_mode) {
-  if (int_mode < HAL_COLOR_MODE_NATIVE || int_mode > HAL_COLOR_MODE_DISPLAY_P3) {
+                                 int32_t /*ColorMode*/ int_mode) {
+  auto mode = static_cast<ColorMode>(int_mode);
+  if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
-  auto mode = static_cast<android_color_mode_t>(int_mode);
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
 }
 
+int32_t HWCSession::SetColorModeWithRenderIntent(hwc2_device_t *device, hwc2_display_t display,
+                                                 int32_t /*ColorMode*/ int_mode,
+                                                 int32_t /*RenderIntent*/ int_render_intent) {
+  auto mode = static_cast<ColorMode>(int_mode);
+  if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+  auto render_intent = static_cast<RenderIntent>(int_render_intent);
+  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorModeWithRenderIntent,
+                                         mode, render_intent);
+}
+
 int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
                                       const float *matrix,
                                       int32_t /*android_color_transform_t*/ hint) {
@@ -892,6 +964,13 @@
       return AsFP<HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES>(HWCSession::GetReadbackBufferAttributes);
     case HWC2::FunctionDescriptor::GetReadbackBufferFence:
       return AsFP<HWC2_PFN_GET_READBACK_BUFFER_FENCE>(HWCSession::GetReadbackBufferFence);
+    case HWC2::FunctionDescriptor::GetRenderIntents:
+      return AsFP<HWC2_PFN_GET_RENDER_INTENTS>(GetRenderIntents);
+    case HWC2::FunctionDescriptor::SetColorModeWithRenderIntent:
+      return AsFP<HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT>(
+          HWCSession::SetColorModeWithRenderIntent);
+    case HWC2::FunctionDescriptor::GetDataspaceSaturationMatrix:
+      return AsFP<HWC2_PFN_GET_DATASPACE_SATURATION_MATRIX>(GetDataspaceSaturationMatrix);
     default:
       DLOGD("Unknown/Unimplemented function descriptor: %d (%s)", int_descriptor,
             to_string(descriptor).c_str());
@@ -1202,6 +1281,14 @@
       status = SetColorModeOverride(input_parcel);
       break;
 
+    case qService::IQService::SET_COLOR_MODE_WITH_RENDER_INTENT:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = SetColorModeWithRenderIntentOverride(input_parcel);
+      break;
+
     case qService::IQService::SET_COLOR_MODE_BY_ID:
       if (!input_parcel) {
         DLOGE("QService command = %d: input_parcel needed.", command);
@@ -1394,7 +1481,7 @@
 
 android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
   auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
-  auto mode = static_cast<android_color_mode_t>(input_parcel->readInt32());
+  auto mode = static_cast<ColorMode>(input_parcel->readInt32());
   auto device = static_cast<hwc2_device_t *>(this);
 
   auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
@@ -1404,6 +1491,20 @@
   return 0;
 }
 
+android::status_t HWCSession::SetColorModeWithRenderIntentOverride(
+    const android::Parcel *input_parcel) {
+  auto display = static_cast<hwc2_display_t>(input_parcel->readInt32());
+  auto mode = static_cast<ColorMode>(input_parcel->readInt32());
+  auto intent = static_cast<RenderIntent>(input_parcel->readInt32());
+  auto device = static_cast<hwc2_device_t *>(this);
+
+  auto err =
+      CallDisplayFunction(device, display, &HWCDisplay::SetColorModeWithRenderIntent, mode, intent);
+  if (err != HWC2_ERROR_NONE)
+    return -EINVAL;
+
+  return 0;
+}
 android::status_t HWCSession::SetColorModeById(const android::Parcel *input_parcel) {
   auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
   auto mode = input_parcel->readInt32();
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index f74179b..119c931 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -73,6 +73,10 @@
   bool init_done_ = false;
 };
 
+constexpr int32_t kDataspaceSaturationMatrixCount = 16;
+constexpr int32_t kDataspaceSaturationPropertyElements = 9;
+constexpr int32_t kPropertyMax = 256;
+
 class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qClient::BnQClient,
                    public HWCDisplayEventHandler {
  public:
@@ -161,7 +165,10 @@
   static int32_t ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
                                  uint32_t *out_num_types, uint32_t *out_num_requests);
   static int32_t SetColorMode(hwc2_device_t *device, hwc2_display_t display,
-                              int32_t /*android_color_mode_t*/ int_mode);
+                              int32_t /*ColorMode*/ int_mode);
+  static int32_t SetColorModeWithRenderIntent(hwc2_device_t *device, hwc2_display_t display,
+                                              int32_t /*ColorMode*/ int_mode,
+                                              int32_t /*RenderIntent*/ int_render_intent);
   static int32_t SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
                                    const float *matrix, int32_t /*android_color_transform_t*/ hint);
   static int32_t GetReadbackBufferAttributes(hwc2_device_t *device, hwc2_display_t display,
@@ -258,6 +265,7 @@
                                           android::Parcel *output_parcel);
   android::status_t SetMixerResolution(const android::Parcel *input_parcel);
   android::status_t SetColorModeOverride(const android::Parcel *input_parcel);
+  android::status_t SetColorModeWithRenderIntentOverride(const android::Parcel *input_parcel);
 
   android::status_t SetColorModeById(const android::Parcel *input_parcel);
   android::status_t getComposerStatus();