Merge "HWC: Set skip to layers with Non Integral Source Crop."
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 867bc05..3dd1c6f 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -35,6 +35,7 @@
 #include <utils/constants.h>
 
 #include <vector>
+#include <utility>
 
 #include "layer_buffer.h"
 #include "sdm_types.h"
@@ -383,6 +384,9 @@
   @sa DisplayInterface::Prepare
   @sa DisplayInterface::Commit
 */
+
+typedef std::pair<ColorPrimaries, GammaTransfer> PrimariesTransfer;
+
 struct LayerStack {
   std::vector<Layer *> layers = {};    //!< Vector of layer pointers.
 
@@ -400,7 +404,8 @@
 
   LayerStackFlags flags;               //!< Flags associated with this layer set.
 
-  ColorPrimaries blend_cs = ColorPrimaries_BT709_5;  //!< o/p - Blending color space updated by SDM
+  PrimariesTransfer blend_cs = {ColorPrimaries_BT709_5, Transfer_sRGB};
+                                       //!< o/p - Blending color space updated by SDM
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 136168b..82d14d9 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1527,7 +1527,7 @@
     // HDR color mode is set when hdr layer is present in layer_stack.
     // If client flags HDR layer as skipped, then blending happens
     // in SDR color space. Hence, need to restore the SDR color mode.
-    if (layer_stack->blend_cs != ColorPrimaries_BT2020) {
+    if (layer_stack->blend_cs.first != ColorPrimaries_BT2020) {
       error = SetHDRMode(false);
       if (error != kErrorNone) {
         DLOGW("Failed to restore SDR mode");
diff --git a/sdm/libs/core/drm/hw_color_manager_drm.cpp b/sdm/libs/core/drm/hw_color_manager_drm.cpp
index 295dafd..85e9574 100644
--- a/sdm/libs/core/drm/hw_color_manager_drm.cpp
+++ b/sdm/libs/core/drm/hw_color_manager_drm.cpp
@@ -917,15 +917,49 @@
 DisplayError HWColorManagerDrm::GetDrmPADither(const PPFeatureInfo &in_data,
                                                DRMPPFeatureInfo *out_data) {
   DisplayError ret = kErrorNone;
-#ifdef PP_DRM_ENABLE
+#if defined(PP_DRM_ENABLE) && defined(DRM_MSM_PA_DITHER)
+  struct SDEPADitherData* sde_dither;
+  struct drm_msm_pa_dither* mdp_dither;
+
   if (!out_data) {
     DLOGE("Invalid input parameter for PA dither");
     return kErrorParameters;
   }
 
-  out_data->id = kPPFeaturesMax;
+  out_data->id = kFeaturePADither;
   out_data->type = sde_drm::kPropBlob;
   out_data->version = in_data.feature_version_;
+
+  out_data->payload_size = sizeof(struct drm_msm_pa_dither);
+  if (in_data.enable_flags_ & kOpsDisable) {
+    /* feature disable case */
+    out_data->payload = NULL;
+    return ret;
+  } else if (!(in_data.enable_flags_ & kOpsEnable)) {
+    out_data->payload = NULL;
+    return kErrorParameters;
+  }
+
+  sde_dither = (struct SDEPADitherData *)in_data.GetConfigData();
+  if (sde_dither->matrix_size != DITHER_MATRIX_SZ) {
+    DLOGE("Invalid dither matrix size %d, exp sz %d",
+          sde_dither->matrix_size, DITHER_MATRIX_SZ);
+    return kErrorParameters;
+  }
+
+  mdp_dither = new drm_msm_pa_dither();
+  if (!mdp_dither) {
+    DLOGE("Failed to allocate memory for dither");
+    return kErrorMemory;
+  }
+
+  mdp_dither->flags = 0;
+  mdp_dither->strength = sde_dither->strength;
+  mdp_dither->offset_en = sde_dither->offset_en;
+  std::memcpy(&mdp_dither->matrix[0],
+              reinterpret_cast<void*>(sde_dither->matrix_data_addr),
+              sizeof(uint32_t) * DITHER_MATRIX_SZ);
+  out_data->payload = mdp_dither;
 #endif
   return ret;
 }
diff --git a/sdm/libs/hwc2/hwc_tonemapper.cpp b/sdm/libs/hwc2/hwc_tonemapper.cpp
index 26caec9..2ae1afc 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.cpp
+++ b/sdm/libs/hwc2/hwc_tonemapper.cpp
@@ -146,22 +146,22 @@
   release_fence_fd_[current_buffer_index_] = dup(fd);
 }
 
-void ToneMapSession::SetToneMapConfig(Layer *layer) {
+void ToneMapSession::SetToneMapConfig(Layer *layer, PrimariesTransfer blend_cs) {
   // HDR -> SDR is FORWARD and SDR - > HDR is INVERSE
   tone_map_config_.type = layer->input_buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
-  tone_map_config_.colorPrimaries = layer->input_buffer.color_metadata.colorPrimaries;
+  tone_map_config_.blend_cs = blend_cs;
   tone_map_config_.transfer = layer->input_buffer.color_metadata.transfer;
   tone_map_config_.secure = layer->request.flags.secure;
   tone_map_config_.format = layer->request.format;
 }
 
-bool ToneMapSession::IsSameToneMapConfig(Layer *layer) {
+bool ToneMapSession::IsSameToneMapConfig(Layer *layer, PrimariesTransfer blend_cs) {
   LayerBuffer& buffer = layer->input_buffer;
   private_handle_t *handle = static_cast<private_handle_t *>(buffer_info_[0].private_data);
   int tonemap_type = buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
 
   return ((tonemap_type == tone_map_config_.type) &&
-          (buffer.color_metadata.colorPrimaries == tone_map_config_.colorPrimaries) &&
+          (blend_cs == tone_map_config_.blend_cs) &&
           (buffer.color_metadata.transfer == tone_map_config_.transfer) &&
           (layer->request.flags.secure == tone_map_config_.secure) &&
           (layer->request.format == tone_map_config_.format) &&
@@ -197,11 +197,11 @@
             return 0;
           }
         }
-        error = AcquireToneMapSession(layer, &session_index);
+        error = AcquireToneMapSession(layer, &session_index, layer_stack->blend_cs);
         fb_session_index_ = INT(session_index);
         break;
       default:
-        error = AcquireToneMapSession(layer, &session_index);
+        error = AcquireToneMapSession(layer, &session_index, layer_stack->blend_cs);
         break;
       }
 
@@ -331,7 +331,8 @@
   CloseFd(acquire_fd);
 }
 
-DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) {
+DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index,
+                                                  PrimariesTransfer blend_cs) {
   // When the property sdm.disable_hdr_lut_gen is set, the lutEntries and gridEntries in
   // the Lut3d will be NULL, clients needs to allocate the memory and set correct 3D Lut
   // for Tonemapping.
@@ -344,7 +345,7 @@
   // Check if we can re-use an existing tone map session.
   for (uint32_t i = 0; i < tone_map_sessions_.size(); i++) {
     ToneMapSession *tonemap_session = tone_map_sessions_.at(i);
-    if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer)) {
+    if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer, blend_cs)) {
       tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) %
                                                 ToneMapSession::kNumIntermediateBuffers;
       tonemap_session->acquired_ = true;
@@ -358,7 +359,7 @@
     return kErrorMemory;
   }
 
-  session->SetToneMapConfig(layer);
+  session->SetToneMapConfig(layer, blend_cs);
 
   ToneMapGetInstanceContext ctx;
   ctx.layer = layer;
diff --git a/sdm/libs/hwc2/hwc_tonemapper.h b/sdm/libs/hwc2/hwc_tonemapper.h
index 8bef3b1..e400d29 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.h
+++ b/sdm/libs/hwc2/hwc_tonemapper.h
@@ -64,7 +64,7 @@
 
 struct ToneMapConfig {
   int type = 0;
-  ColorPrimaries colorPrimaries = ColorPrimaries_Max;
+  PrimariesTransfer blend_cs = {ColorPrimaries_BT709_5, Transfer_sRGB};
   GammaTransfer transfer = Transfer_Max;
   LayerBufferFormat format = kFormatRGBA8888;
   bool secure = false;
@@ -78,8 +78,8 @@
   void FreeIntermediateBuffers();
   void UpdateBuffer(int acquire_fence, LayerBuffer *buffer);
   void SetReleaseFence(int fd);
-  void SetToneMapConfig(Layer *layer);
-  bool IsSameToneMapConfig(Layer *layer);
+  void SetToneMapConfig(Layer *layer, PrimariesTransfer blend_cs);
+  bool IsSameToneMapConfig(Layer *layer, PrimariesTransfer blend_cs);
 
   // TaskHandler methods implementation.
   virtual void OnTask(const ToneMapTaskCode &task_code,
@@ -110,7 +110,7 @@
 
  private:
   void ToneMap(Layer *layer, ToneMapSession *session);
-  DisplayError AcquireToneMapSession(Layer *layer, uint32_t *session_index);
+  DisplayError AcquireToneMapSession(Layer *layer, uint32_t *sess_idx, PrimariesTransfer blend_cs);
   void DumpToneMapOutput(ToneMapSession *session, int *acquire_fence);
 
   std::vector<ToneMapSession*> tone_map_sessions_;