Merge "sdm: Add support to change minimum encription level for hdcp"
diff --git a/gralloc/gr_utils.cpp b/gralloc/gr_utils.cpp
index 1ecbce3..7c825bd 100644
--- a/gralloc/gr_utils.cpp
+++ b/gralloc/gr_utils.cpp
@@ -1150,11 +1150,14 @@
   // the usage bits, gralloc assigns a format.
   if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
       format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
-    if (usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC || usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC_PI) {
+    if ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC || usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC_PI)
+        && format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
       gr_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
     } else if (usage & BufferUsage::VIDEO_ENCODER) {
       if (usage & GRALLOC_USAGE_PRIVATE_VIDEO_NV21_ENCODER) {
         gr_format = HAL_PIXEL_FORMAT_NV21_ENCODEABLE;  // NV21
+      } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+        gr_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;
       } else {
         gr_format = HAL_PIXEL_FORMAT_NV12_ENCODEABLE;  // NV12
       }
diff --git a/include/display_properties.h b/include/display_properties.h
index c321b98..ddcde64 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -106,6 +106,7 @@
 #define QDCM_DIAGONAL_MATRIXMODE_PROP        DISPLAY_PROP("qdcm.diagonal_matrix_mode")
 #define QDCM_DISABLE_TIMEOUT_PROP            PERSIST_DISPLAY_PROP("qdcm.disable_timeout")
 #define QDCM_MODE_COMBINE_PROP               DISPLAY_PROP("qdcm.mode_combine")
+#define PREFER_MULTIRECT_PROP                DISPLAY_PROP("prefer_multirect")
 
 #define ZERO_SWAP_INTERVAL                   "vendor.debug.egl.swapinterval"
 
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 5685064..c352839 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -801,6 +801,7 @@
    * [return]: Error code if the API fails, 0 on success.
    */
   virtual int Commit(bool synchronous, bool retain_planes) = 0;
+
   /*
    * Validate the params set via Perform().
    * [return]: Error code if the API fails, 0 on success.
@@ -923,6 +924,7 @@
    * [return]: Error code if the API fails, 0 on success.
    */
   virtual int DestroyAtomicReq(DRMAtomicReqInterface *intf) = 0;
+
   /*
    * Sets the global scaler LUT
    * [input]: LUT Info
@@ -931,6 +933,13 @@
   virtual int SetScalerLUT(const DRMScalerLUTInfo &lut_info) = 0;
 
   /*
+   * Unsets the global scaler LUT
+   * [input]: None
+   * [return]: Error code if the API fails, 0 on success.
+   */
+  virtual int UnsetScalerLUT() = 0;
+
+  /*
    * Get the DPPS feature info
    * [input]: Dpps feature id, info->id
    * [output]: Dpps feature version, info->version
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index afc8433..6d54b4e 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -116,12 +116,14 @@
   fb_config_.x_pixels = mixer_attributes_.width;
   fb_config_.y_pixels = mixer_attributes_.height;
 
-  HWScaleLutInfo lut_info = {};
-  error = comp_manager_->GetScaleLutConfig(&lut_info);
-  if (error == kErrorNone) {
-    error = hw_intf_->SetScaleLutConfig(&lut_info);
-    if (error != kErrorNone) {
-      goto CleanupOnError;
+  if (IsPrimaryDisplay()) {
+    HWScaleLutInfo lut_info = {};
+    error = comp_manager_->GetScaleLutConfig(&lut_info);
+    if (error == kErrorNone) {
+      error = hw_intf_->SetScaleLutConfig(&lut_info);
+      if (error != kErrorNone) {
+        goto CleanupOnError;
+      }
     }
   }
 
@@ -182,6 +184,9 @@
     lock_guard<recursive_mutex> obj(recursive_mutex_);
     ClearColorInfo();
     comp_manager_->UnregisterDisplay(display_comp_ctx_);
+    if (IsPrimaryDisplay()) {
+      hw_intf_->UnsetScaleLutConfig();
+    }
   }
   HWEventsInterface::Destroy(hw_events_intf_);
   HWInterface::Destroy(hw_intf_);
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 02c534d..f93ac18 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -463,7 +463,10 @@
         error = kErrorParameters;
         break;
       }
-      error = hw_intf_->SetDppsFeature(payload, size);
+      {
+        lock_guard<recursive_mutex> obj(recursive_mutex_);
+        error = hw_intf_->SetDppsFeature(payload, size);
+      }
       break;
     case kDppsGetFeatureInfo:
       if (!payload) {
@@ -491,7 +494,10 @@
         error = kErrorParameters;
         break;
       }
-      commit_event_enabled_ = *(reinterpret_cast<bool *>(payload));
+      {
+        lock_guard<recursive_mutex> obj(recursive_mutex_);
+        commit_event_enabled_ = *(reinterpret_cast<bool *>(payload));
+      }
       break;
     default:
       DLOGE("Invalid input op %d", op);
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index 3b334d0..cff7519 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -61,16 +61,6 @@
     hw_intf_->GetDisplayId(&display_id_);
   }
 
-  HWScaleLutInfo lut_info = {};
-  error = comp_manager_->GetScaleLutConfig(&lut_info);
-  if (error == kErrorNone) {
-    error = hw_intf_->SetScaleLutConfig(&lut_info);
-    if (error != kErrorNone) {
-      HWInterface::Destroy(hw_intf_);
-      return error;
-    }
-  }
-
   if (hw_info_intf_) {
     HWResourceInfo hw_resource_info = HWResourceInfo();
     hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 4cb06c7..8311084 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -1615,6 +1615,12 @@
   return kErrorNone;
 }
 
+DisplayError HWDeviceDRM::UnsetScaleLutConfig() {
+  drm_mgr_intf_->UnsetScalerLUT();
+
+  return kErrorNone;
+}
+
 DisplayError HWDeviceDRM::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
   if (IsResolutionSwitchEnabled()) {
     return kErrorNotSupported;
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index b89391b..6cfd51c 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -104,6 +104,7 @@
   virtual DisplayError SetAutoRefresh(bool enable) { autorefresh_ = enable; return kErrorNone; }
   virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
   virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+  virtual DisplayError UnsetScaleLutConfig();
   virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
   virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
   virtual void InitializeConfigs();
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index df8b462..29a4660 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -29,6 +29,7 @@
 
 #include <utils/debug.h>
 #include <vector>
+#include <cstring>
 
 #include "hw_peripheral_drm.h"
 
@@ -60,13 +61,14 @@
   }
 
   scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
+  dest_scalar_cache_.resize(hw_resource_.hw_dest_scalar_info.count);
 
   return kErrorNone;
 }
 
 DisplayError HWPeripheralDRM::Validate(HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
-  SetDestScalarData(hw_layer_info);
+  SetDestScalarData(hw_layer_info, true);
   SetupConcurrentWriteback(hw_layer_info, true);
   SetIdlePCState();
 
@@ -75,7 +77,7 @@
 
 DisplayError HWPeripheralDRM::Commit(HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
-  SetDestScalarData(hw_layer_info);
+  SetDestScalarData(hw_layer_info, false);
   SetupConcurrentWriteback(hw_layer_info, false);
   SetIdlePCState();
 
@@ -98,15 +100,16 @@
   sde_dest_scalar_data_ = {};
   for (uint32_t j = 0; j < scalar_data_.size(); j++) {
     scalar_data_[j] = {};
+    dest_scalar_cache_[j] = {};
   }
 }
 
-void HWPeripheralDRM::SetDestScalarData(HWLayersInfo hw_layer_info) {
+void HWPeripheralDRM::SetDestScalarData(HWLayersInfo hw_layer_info, bool validate) {
   if (!hw_scale_ || !hw_resource_.hw_dest_scalar_info.count) {
     return;
   }
 
-  uint32_t index = 0;
+  uint32_t count = 0;
   for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
     DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
 
@@ -115,9 +118,10 @@
     }
 
     HWDestScaleInfo *dest_scale_info = it->second;
-    SDEScaler *scale = &scalar_data_[index];
+    SDEScaler *scale = &scalar_data_[count];
     hw_scale_->SetScaler(dest_scale_info->scale_data, scale);
-    sde_drm_dest_scaler_cfg *dest_scalar_data = &sde_dest_scalar_data_.ds_cfg[index];
+
+    sde_drm_dest_scaler_cfg *dest_scalar_data = &sde_dest_scalar_data_.ds_cfg[count];
     dest_scalar_data->flags = 0;
     if (scale->scaler_v2.enable) {
       dest_scalar_data->flags |= SDE_DRM_DESTSCALER_ENABLE;
@@ -128,18 +132,30 @@
     if (dest_scale_info->scale_update) {
       dest_scalar_data->flags |= SDE_DRM_DESTSCALER_SCALE_UPDATE;
     }
+    if (hw_panel_info_.partial_update) {
+      dest_scalar_data->flags |= SDE_DRM_DESTSCALER_PU_ENABLE;
+    }
+
+    if (!std::memcmp(&dest_scalar_cache_[count].scalar_data, scale, sizeof(SDEScaler)) &&
+        dest_scalar_cache_[count].flags == dest_scalar_data->flags) {
+      continue;
+    }
+
     dest_scalar_data->index = i;
     dest_scalar_data->lm_width = dest_scale_info->mixer_width;
     dest_scalar_data->lm_height = dest_scale_info->mixer_height;
     dest_scalar_data->scaler_cfg = reinterpret_cast<uint64_t>(&scale->scaler_v2);
-    if (hw_panel_info_.partial_update) {
-      dest_scalar_data->flags |= SDE_DRM_DESTSCALER_PU_ENABLE;
+    if (!validate) {
+      dest_scalar_cache_[count].flags = dest_scalar_data->flags;
+      dest_scalar_cache_[count].scalar_data = *scale;
     }
-    index++;
+    count++;
   }
-  sde_dest_scalar_data_.num_dest_scaler = UINT32(hw_layer_info.dest_scale_info_map.size());
-  drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DEST_SCALER_CONFIG, token_.crtc_id,
-                            reinterpret_cast<uint64_t>(&sde_dest_scalar_data_));
+  if (count) {
+    sde_dest_scalar_data_.num_dest_scaler = count;
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DEST_SCALER_CONFIG, token_.crtc_id,
+                              reinterpret_cast<uint64_t>(&sde_dest_scalar_data_));
+  }
 }
 
 DisplayError HWPeripheralDRM::Flush() {
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
index 0ded3e1..e693163 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.h
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -58,7 +58,7 @@
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence);
 
  private:
-  void SetDestScalarData(HWLayersInfo hw_layer_info);
+  void SetDestScalarData(HWLayersInfo hw_layer_info, bool validate);
   void ResetDisplayParams();
   DisplayError SetupConcurrentWritebackModes();
   void SetupConcurrentWriteback(const HWLayersInfo &hw_layer_info, bool validate);
@@ -69,10 +69,16 @@
                               idle_pc_state_);
   }
 
+  struct DestScalarCache {
+    SDEScaler scalar_data = {};
+    uint32_t flags = {};
+  };
+
   sde_drm_dest_scaler_data sde_dest_scalar_data_ = {};
   std::vector<SDEScaler> scalar_data_ = {};
   CWBConfig cwb_config_ = {};
   sde_drm::DRMIdlePCState idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
+  std::vector<DestScalarCache> dest_scalar_cache_ = {};
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_virtual_drm.h b/sdm/libs/core/drm/hw_virtual_drm.h
index 9dfc409..61f498b 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.h
+++ b/sdm/libs/core/drm/hw_virtual_drm.h
@@ -53,6 +53,12 @@
   virtual DisplayError Commit(HWLayers *hw_layers);
   virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence);
+  virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError UnsetScaleLutConfig() {
+    return kErrorNotSupported;
+  }
 
  private:
   void ConfigureWbConnectorFbId(uint32_t fb_id);
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index cf77e09..7504721 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -95,6 +95,7 @@
   virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; }
   virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
   virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+  virtual DisplayError UnsetScaleLutConfig() { return kErrorNotSupported; }
   virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
   virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
   virtual DisplayError DumpDebugData();
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index b5223b5..06d166e 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -111,6 +111,7 @@
   virtual DisplayError SetAutoRefresh(bool enable) = 0;
   virtual DisplayError SetS3DMode(HWS3DMode s3d_mode) = 0;
   virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
+  virtual DisplayError UnsetScaleLutConfig() = 0;
   virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) = 0;
   virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes) = 0;
   virtual DisplayError DumpDebugData() = 0;
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 4f558bc..6072397 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -204,6 +204,9 @@
   bool IsSkipValidateState() { return (validate_state_ == kSkipValidate); }
   bool IsInternalValidateState() { return (validated_ && (validate_state_ == kInternalValidate)); }
   void SetValidationState(DisplayValidateState state) { validate_state_ = state; }
+  ColorMode GetCurrentColorMode() {
+    return (color_mode_ ? color_mode_->GetCurrentColorMode() : ColorMode::SRGB);
+  }
 
   // HWC2 APIs
   virtual HWC2::Error AcceptDisplayChanges(void);
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 4237b56..61e2619 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -73,6 +73,25 @@
 Locker HWCSession::locker_[kNumDisplays];
 static const int kSolidFillDelay = 100 * 1000;
 
+// Map the known color modes to dataspace.
+static int32_t GetDataspace(ColorMode mode) {
+  switch (mode) {
+    case ColorMode::SRGB:
+    case ColorMode::NATIVE:
+      return HAL_DATASPACE_V0_SRGB;
+    case ColorMode::DCI_P3:
+      return HAL_DATASPACE_DCI_P3;
+    case ColorMode::DISPLAY_P3:
+      return HAL_DATASPACE_DISPLAY_P3;
+    case ColorMode::BT2100_PQ:
+      return HAL_DATASPACE_BT2020_PQ;
+    case ColorMode::BT2100_HLG:
+      return HAL_DATASPACE_BT2020_HLG;
+    default:
+      return HAL_DATASPACE_UNKNOWN;
+  }
+}
+
 void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
   const char *uevent_thread_name = "HWC_UeventThread";
 
@@ -394,15 +413,14 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
   Locker::ScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
-  DLOGI("Destroying virtual display id:%" PRIu64, display);
   auto *hwc_session = static_cast<HWCSession *>(device);
 
   if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
     std :: bitset < kSecureMax > secure_sessions = 0;
     hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]->GetActiveSecureSession(&secure_sessions);
     if (secure_sessions.any()) {
+      DLOGI("Destroying virtual display id:%" PRIu64, display);
       DLOGW("Secure session is active, deferring destruction of virtual display");
       hwc_session->destroy_virtual_disp_pending_ = true;
       return HWC2_ERROR_NONE;
@@ -2449,10 +2467,16 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  *format = HAL_PIXEL_FORMAT_RGB_888;
-  *dataspace = HAL_DATASPACE_V0_SRGB;  // ((STANDARD_BT709 | TRANSFER_SRGB) | RANGE_FULL)
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  HWCDisplay *hwc_display = hwc_session->hwc_display_[display];
 
-  return HWC2_ERROR_NONE;
+  if (hwc_display) {
+    *format = HAL_PIXEL_FORMAT_RGB_888;
+    *dataspace = GetDataspace(hwc_display->GetCurrentColorMode());
+    return HWC2_ERROR_NONE;
+  }
+
+  return HWC2_ERROR_BAD_DISPLAY;
 }
 
 int32_t HWCSession::SetReadbackBuffer(hwc2_device_t *device, hwc2_display_t display,