sdm: Add support for single buffer layers

Add support for single buffer layers. Graphics writes to the same
buffer being read by display. For dumb panels, there should be no
idle mode, smart panels should be put in an auto-refresh mode. Also
such layers cannot be sent to framebuffer.
Change-Id: Id4f15239d8edc258524dfddd4e9d72c67cd2406f
CRs-fixed: 1114808
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index cd89d41..7966053 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -809,6 +809,17 @@
       }
     } break;
 
+    case GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE: {
+      private_handle_t* hnd =  va_arg(args, private_handle_t*);
+      uint32_t *enable = va_arg(args, uint32_t*);
+      if (private_handle_t::validate(hnd) != 0) {
+        return GRALLOC1_ERROR_BAD_HANDLE;
+      }
+      if (setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable) != 0) {
+        return GRALLOC1_ERROR_UNSUPPORTED;
+      }
+    } break;
+
     default:
       break;
   }
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 51b485e..43235bf 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -529,6 +529,12 @@
       secure_display_active = true;
     }
 
+    if (hwc_layer->IsSingleBuffered() &&
+       !(hwc_layer->IsRotationPresent() || hwc_layer->IsScalingPresent())) {
+      layer->flags.single_buffer = true;
+      layer_stack_.flags.single_buffered_layer_present = true;
+    }
+
     if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor) {
       // Currently we support only one HWCursor & only at top most z-order
       if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
@@ -2039,7 +2045,8 @@
   }
 
   // Layer Stack checks
-  if (layer_stack_.flags.hdr_present && (tone_mapper_ && tone_mapper_->IsActive())) {
+  if ((layer_stack_.flags.hdr_present && (tone_mapper_ && tone_mapper_->IsActive())) ||
+     layer_stack_.flags.single_buffered_layer_present) {
     DLOGV_IF(kTagClient, "HDR content present with tone mapping enabled. Returning false.");
     return false;
   }
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index bf660b5..d88c9fc 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -769,6 +769,9 @@
     GetUBWCStatsFromMetaData(&cr_stats[0], &(layer_buffer->ubwc_crstats[0]));
   }  // if (getMetaData)
 
+  single_buffer_ = false;
+  getMetaData(const_cast<private_handle_t *>(handle), GET_SINGLE_BUFFER_MODE, &single_buffer_);
+
   return kErrorNone;
 }
 
@@ -888,4 +891,19 @@
   return fence;
 }
 
+bool HWCLayer::IsRotationPresent() {
+  return ((layer_->transform.rotation != 0.0f) ||
+         layer_->transform.flip_horizontal ||
+         layer_->transform.flip_vertical);
+}
+
+bool HWCLayer::IsScalingPresent() {
+  uint32_t src_width  = static_cast<uint32_t>(layer_->src_rect.right - layer_->src_rect.left);
+  uint32_t src_height = static_cast<uint32_t>(layer_->src_rect.bottom - layer_->src_rect.top);
+  uint32_t dst_width  = static_cast<uint32_t>(layer_->dst_rect.right - layer_->dst_rect.left);
+  uint32_t dst_height = static_cast<uint32_t>(layer_->dst_rect.bottom - layer_->dst_rect.top);
+
+  return ((src_width != dst_width) || (dst_height != src_height));
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index a7b65c8..5f5792f 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -94,6 +94,9 @@
   bool SupportLocalConversion(ColorPrimaries working_primaries);
   void ResetValidation() { needs_validate_ = false; }
   bool NeedsValidation() { return (needs_validate_ || geometry_changes_); }
+  bool IsSingleBuffered() { return single_buffer_; }
+  bool IsScalingPresent();
+  bool IsRotationPresent();
 
  private:
   Layer *layer_ = nullptr;
@@ -107,6 +110,7 @@
   LayerTransform layer_transform_ = {};
   LayerRect dst_rect_ = {};
   bool needs_validate_ = true;
+  bool single_buffer_ = false;
 
   // Composition requested by client(SF)
   HWC2::Composition client_requested_ = HWC2::Composition::Device;