Merge "Gralloc: Add UBWC support for AHWB formats."
diff --git a/gralloc/gr_adreno_info.cpp b/gralloc/gr_adreno_info.cpp
index 446c373..8644ef7 100644
--- a/gralloc/gr_adreno_info.cpp
+++ b/gralloc/gr_adreno_info.cpp
@@ -86,6 +86,12 @@
       !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
     gfx_ubwc_disable_ = true;
   }
+
+  property_get(DISABLE_AHARDWAREBUFFER_PROP, property, "0");
+  if (!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+      !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+    gfx_ahardware_buffer_disable_ = true;
+  }
 }
 
 AdrenoMemInfo::~AdrenoMemInfo() {
@@ -263,6 +269,10 @@
 }
 
 bool AdrenoMemInfo::AdrenoSizeAPIAvaliable() {
+  if (gfx_ahardware_buffer_disable_) {
+    return false;
+  }
+
   return (LINK_adreno_get_metadata_blob_size && LINK_adreno_init_memory_layout &&
           LINK_adreno_get_aligned_gpu_buffer_size);
 }
diff --git a/gralloc/gr_adreno_info.h b/gralloc/gr_adreno_info.h
index e834293..bb8fdd6 100644
--- a/gralloc/gr_adreno_info.h
+++ b/gralloc/gr_adreno_info.h
@@ -193,6 +193,7 @@
   int (*LINK_adreno_isPISupportedByGpu)(int format, uint64_t usage) = NULL;
 
   bool gfx_ubwc_disable_ = false;
+  bool gfx_ahardware_buffer_disable_ = false;
   void *libadreno_utils_ = NULL;
 
   static AdrenoMemInfo *s_instance;
diff --git a/gralloc/gr_utils.cpp b/gralloc/gr_utils.cpp
index 16cdce8..dc64b58 100644
--- a/gralloc/gr_utils.cpp
+++ b/gralloc/gr_utils.cpp
@@ -218,6 +218,21 @@
   return align;
 }
 
+bool IsGPUFlagSupported(uint64_t usage) {
+  bool ret = true;
+  if ((usage & BufferUsage::GPU_MIPMAP_COMPLETE)) {
+    ALOGE("GPU_MIPMAP_COMPLETE not supported");
+    ret = false;
+  }
+
+  if ((usage & BufferUsage::GPU_CUBE_MAP)) {
+    ALOGE("GPU_CUBE_MAP not supported");
+    ret = false;
+  }
+
+  return ret;
+}
+
 // Returns the final buffer size meant to be allocated with ion
 unsigned int GetSize(const BufferInfo &info, unsigned int alignedw, unsigned int alignedh) {
   unsigned int size = 0;
@@ -226,6 +241,11 @@
   int height = info.height;
   uint64_t usage = info.usage;
 
+  if (!IsGPUFlagSupported(usage)) {
+    ALOGE("Unsupported GPU usage flags present 0x%" PRIx64, usage);
+    return 0;
+  }
+
   if (IsUBwcEnabled(format, usage)) {
     size = GetUBwcSize(width, height, format, alignedw, alignedh);
   } else if (IsUncompressedRGBFormat(format)) {
diff --git a/gralloc/gr_utils.h b/gralloc/gr_utils.h
index d273754..c955619 100644
--- a/gralloc/gr_utils.h
+++ b/gralloc/gr_utils.h
@@ -115,6 +115,7 @@
 int GetImplDefinedFormat(uint64_t usage, int format);
 int GetCustomFormatFlags(int format, uint64_t usage, int *custom_format, uint64_t *priv_flags);
 int GetBufferType(int inputFormat);
+bool IsGPUFlagSupported(uint64_t usage);
 }  // namespace gralloc
 
 #endif  // __GR_UTILS_H__
diff --git a/gralloc/gralloc_priv.h b/gralloc/gralloc_priv.h
index 45e1240..4c981d4 100644
--- a/gralloc/gralloc_priv.h
+++ b/gralloc/gralloc_priv.h
@@ -28,6 +28,7 @@
 #define GRALLOC_PROP(prop_name) GRALLOC_PROP_PREFIX prop_name
 
 #define DISABLE_UBWC_PROP                    GRALLOC_PROP("disable_ubwc")
+#define DISABLE_AHARDWAREBUFFER_PROP         GRALLOC_PROP("disable_ahardware_buffer")
 #define ENABLE_FB_UBWC_PROP                  GRALLOC_PROP("enable_fb_ubwc")
 #define MAP_FB_MEMORY_PROP                   GRALLOC_PROP("map_fb_memory")
 #define USE_SYSTEM_HEAP_FOR_SENSORS          GRALLOC_PROP("use_system_heap_for_sensors")
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 7b38d24..02ea903 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -178,6 +178,7 @@
   uint32_t max_luminance = 0;          //!< From Panel's peak luminance
   uint32_t average_luminance = 0;      //!< From Panel's average luminance
   uint32_t min_luminance = 0;          //!< From Panel's blackness level
+  bool partial_update = false;         //!< If display supports Partial Update.
 };
 
 /*! @brief This structure defines configuration for variable properties of a display device.
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 2a05abd..9152616 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -458,6 +458,7 @@
   fixed_info->min_luminance = fixed_info->hdr_supported ?  hw_panel_info_.blackness_level: 0;
   fixed_info->hdr_eotf = hw_panel_info_.hdr_eotf;
   fixed_info->hdr_metadata_type_one = hw_panel_info_.hdr_metadata_type_one;
+  fixed_info->partial_update = hw_panel_info_.partial_update;
 
   return kErrorNone;
 }
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 0e2c16e..4cf0db3 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -383,6 +383,12 @@
   current_refresh_rate_ = max_refresh_rate_;
 
   GetUnderScanConfig();
+
+  DisplayConfigFixedInfo fixed_info = {};
+  display_intf_->GetConfig(&fixed_info);
+  partial_update_enabled_ = fixed_info.partial_update;
+  client_target_->SetPartialUpdate(partial_update_enabled_);
+
   DLOGI("Display created with id: %d", id_);
 
   return 0;
@@ -426,6 +432,7 @@
   geometry_changes_ |= GeometryChanges::kAdded;
   validated_ = false;
   layer_stack_invalid_ = true;
+  layer->SetPartialUpdate(partial_update_enabled_);
 
   return HWC2::Error::None;
 }
@@ -579,7 +586,7 @@
 
     layer->flags.updating = true;
     if (layer_set_.size() <= kMaxLayerCount) {
-      layer->flags.updating = IsLayerUpdating(layer);
+      layer->flags.updating = IsLayerUpdating(hwc_layer);
     }
 
     layer_stack_.layers.push_back(layer);
@@ -589,7 +596,7 @@
   layer_stack_.flags.geometry_changed = UINT32(geometry_changes_ > 0);
   // Append client target to the layer stack
   Layer *sdm_client_target = client_target_->GetSDMLayer();
-  sdm_client_target->flags.updating = IsLayerUpdating(sdm_client_target);
+  sdm_client_target->flags.updating = IsLayerUpdating(client_target_);
   layer_stack_.layers.push_back(sdm_client_target);
   // fall back frame composition to GPU when client target is 10bit
   // TODO(user): clarify the behaviour from Client(SF) and SDM Extn -
@@ -1911,24 +1918,17 @@
   return updating_count;
 }
 
-bool HWCDisplay::IsLayerUpdating(const Layer *layer) {
+bool HWCDisplay::IsLayerUpdating(HWCLayer *hwc_layer) {
+  auto layer = hwc_layer->GetSDMLayer();
   // Layer should be considered updating if
   //   a) layer is in single buffer mode, or
   //   b) valid dirty_regions(android specific hint for updating status), or
   //   c) layer stack geometry has changed (TODO(user): Remove when SDM accepts
   //      geometry_changed as bit fields).
-  return (layer->flags.single_buffer || IsSurfaceUpdated(layer->dirty_regions) ||
+  return (layer->flags.single_buffer || hwc_layer->IsSurfaceUpdated() ||
           geometry_changes_);
 }
 
-bool HWCDisplay::IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions) {
-  // based on dirty_regions determine if its updating
-  // dirty_rect count = 0 - whole layer - updating.
-  // dirty_rect count = 1 or more valid rects - updating.
-  // dirty_rect count = 1 with (0,0,0,0) - not updating.
-  return (dirty_regions.empty() || IsValid(dirty_regions.at(0)));
-}
-
 uint32_t HWCDisplay::SanitizeRefreshRate(uint32_t req_refresh_rate) {
   uint32_t refresh_rate = req_refresh_rate;
 
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 02e3cc6..84218ac 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -294,8 +294,7 @@
   void MarkLayersForClientComposition(void);
   virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
   uint32_t GetUpdatingLayersCount(void);
-  bool IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions);
-  bool IsLayerUpdating(const Layer *layer);
+  bool IsLayerUpdating(HWCLayer *layer);
   uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
   virtual void GetUnderScanConfig() { }
 
@@ -362,6 +361,7 @@
   int null_display_mode_ = 0;
   bool has_client_composition_ = false;
   DisplayValidateState validate_state_ = kNormalValidate;
+  bool partial_update_enabled_ = false;
 };
 
 inline int HWCDisplay::Perform(uint32_t operation, ...) {
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index 97d74ef..1dcf0f2 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -152,11 +152,7 @@
   }
 
   if (display_paused_) {
-    DisplayError error = display_intf_->Flush();
     validated_ = false;
-    if (error != kErrorNone) {
-      DLOGE("Flush failed. Error = %d", error);
-    }
   } else {
     status = HWCDisplay::CommitLayerStack();
     if (status == HWC2::Error::None) {
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 840119e..b4b3e34 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -305,7 +305,21 @@
 }
 
 HWC2::Error HWCLayer::SetLayerSurfaceDamage(hwc_region_t damage) {
-  // Check if there is an update in SurfaceDamage rects
+  surface_updated_ = true;
+  if ((damage.numRects == 1) && (damage.rects[0].bottom == 0) && (damage.rects[0].right == 0)) {
+    surface_updated_ = false;
+  }
+
+  if (!layer_->flags.updating && surface_updated_) {
+    needs_validate_ = true;
+  }
+
+  if (!partial_update_enabled_) {
+    SetDirtyRegions(damage);
+    return HWC2::Error::None;
+  }
+
+  // Check if there is an update in SurfaceDamage rects.
   if (layer_->dirty_regions.size() != damage.numRects) {
     needs_validate_ = true;
   } else {
@@ -319,12 +333,7 @@
     }
   }
 
-  layer_->dirty_regions.clear();
-  for (uint32_t i = 0; i < damage.numRects; i++) {
-    LayerRect rect;
-    SetRect(damage.rects[i], &rect);
-    layer_->dirty_regions.push_back(rect);
-  }
+  SetDirtyRegions(damage);
   return HWC2::Error::None;
 }
 
@@ -1002,4 +1011,13 @@
   return ((src_width != dst_width) || (dst_height != src_height));
 }
 
+void HWCLayer::SetDirtyRegions(hwc_region_t surface_damage) {
+  layer_->dirty_regions.clear();
+  for (uint32_t i = 0; i < surface_damage.numRects; i++) {
+    LayerRect rect;
+    SetRect(surface_damage.rects[i], &rect);
+    layer_->dirty_regions.push_back(rect);
+  }
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index d72f07f..46e83cb 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -107,6 +107,8 @@
   bool IsRotationPresent();
   bool IsDataSpaceSupported();
   static LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
+  bool IsSurfaceUpdated() { return surface_updated_; }
+  void SetPartialUpdate(bool enabled) { partial_update_enabled_ = enabled; }
 
  private:
   Layer *layer_ = nullptr;
@@ -123,6 +125,8 @@
   bool single_buffer_ = false;
   int buffer_fd_ = -1;
   bool dataspace_supported_ = false;
+  bool partial_update_enabled_ = false;
+  bool surface_updated_ = true;
 
   // Composition requested by client(SF)
   HWC2::Composition client_requested_ = HWC2::Composition::Device;
@@ -139,6 +143,7 @@
   DisplayError SetIGC(IGC_t source, LayerIGC *target);
   uint32_t RoundToStandardFPS(float fps);
   void ValidateAndSetCSC(const private_handle_t *handle);
+  void SetDirtyRegions(hwc_region_t surface_damage);
 };
 
 struct SortLayersByZ {