Merge "hwc2: Skip SDM prepare for consecutive GPU composed frames" into pi-dev
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index b53610b..15add54 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1062,6 +1062,11 @@
   }
 
   UpdateRefreshRate();
+
+  if (CanSkipSdmPrepare(out_num_types, out_num_requests)) {
+    return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
+  }
+
   if (!skip_prepare_) {
     DisplayError error = display_intf_->Prepare(&layer_stack_);
     if (error != kErrorNone) {
@@ -2168,4 +2173,37 @@
   }
 }
 
+// Skip SDM prepare if all the layers in the current draw cycle are marked as Skip and
+// previous draw cycle had GPU Composition, as the resources for GPU Target layer have
+// already been validated and configured to the driver.
+bool HWCDisplay::CanSkipSdmPrepare(uint32_t *num_types, uint32_t *num_requests) {
+  if (!validated_ || layer_set_.empty()) {
+    return false;
+  }
+
+  bool skip_prepare = true;
+  for (auto hwc_layer : layer_set_) {
+    if (!hwc_layer->GetSDMLayer()->flags.skip ||
+        (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Client)) {
+      skip_prepare = false;
+      layer_changes_.clear();
+      break;
+    }
+    if (hwc_layer->GetClientRequestedCompositionType() != HWC2::Composition::Client) {
+      layer_changes_[hwc_layer->GetId()] = HWC2::Composition::Client;
+    }
+  }
+
+  if (skip_prepare) {
+    *num_types = UINT32(layer_changes_.size());
+    *num_requests = 0;
+    layer_stack_invalid_ = false;
+    has_client_composition_ = true;
+    client_target_->ResetValidation();
+    validate_state_ = kNormalValidate;
+  }
+
+  return skip_prepare;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 8cbd6bb..084a2a5 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -345,6 +345,8 @@
  private:
   void DumpInputBuffers(void);
   void UpdateRefreshRate();
+  bool CanSkipSdmPrepare(uint32_t *num_types, uint32_t *num_requests);
+
   qService::QService *qservice_ = NULL;
   DisplayClass display_class_;
   uint32_t geometry_changes_ = GeometryChanges::kNone;