Merge "sde: Set the recommended rotator output format for NV21"
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index f4c4415..782d8fc 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -95,9 +95,10 @@
   float fps;                  //!< Frame rate per second.
   uint32_t vsync_period_ns;   //!< VSync period in nanoseconds.
   uint32_t v_total;           //!< Total lines in Y-direction (vActive + vFP + vBP + vPulseWidth).
+  uint32_t h_total;           //!< Total width of panel (hActive + hFP + hBP + hPulseWidth).
 
   DisplayConfigVariableInfo() : x_pixels(0), y_pixels(0), x_dpi(0.0f), y_dpi(0.0f),
-                               fps(0.0f), vsync_period_ns(0) { }
+                               fps(0.0f), vsync_period_ns(0), v_total(0), h_total(0) { }
 };
 
 /*! @brief Event data associated with VSync event.
diff --git a/displayengine/include/private/strategy_interface.h b/displayengine/include/private/strategy_interface.h
index eac88cc..df01c7f 100644
--- a/displayengine/include/private/strategy_interface.h
+++ b/displayengine/include/private/strategy_interface.h
@@ -31,6 +31,7 @@
 
 #include <core/sde_types.h>
 #include <core/display_interface.h>
+#include "hw_info_types.h"
 
 namespace sde {
 
@@ -88,11 +89,14 @@
 
   @param[in] version \link STRATEGY_VERSION_TAG \endlink
   @param[in] type \link DisplayType \endlink
+  @param[in] hw_resource_info \link HWResourceInfo \endlink
+  @param[in] hw_panel_info \link HWPanelInfo \endlink
   @param[out] interface \link StrategyInterface \endlink
 
   @return \link DisplayError \endlink
 */
 typedef DisplayError (*CreateStrategyInterface)(uint16_t version, DisplayType type,
+                      const HWResourceInfo *hw_resource_info, const HWPanelInfo *hw_panel_info,
                       StrategyInterface **interface);
 
 /*! @brief Function to destroy composer strategy interface.
@@ -139,6 +143,13 @@
 
   uint32_t count;           //!< Total number of layers which need to be set on hardware.
 
+  LayerRect left_partial_update;
+                            //!< Left ROI.
+
+  LayerRect right_partial_update;
+                            //!< Right ROI.
+
+
   HWLayersInfo() : stack(NULL), count(0) { }
 };
 
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
index 5f65834..2cef5d7 100644
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -65,6 +65,7 @@
   static uint32_t GetIdleTimeoutMs();
   static bool IsRotatorDownScaleDisabled();
   static bool IsDecimationDisabled();
+  static bool IsPartialUpdate();
 
  private:
   Debug();
diff --git a/displayengine/include/utils/rect.h b/displayengine/include/utils/rect.h
index 0730529..dd60672 100644
--- a/displayengine/include/utils/rect.h
+++ b/displayengine/include/utils/rect.h
@@ -37,11 +37,14 @@
 
 namespace sde {
 
-  bool IsValidRect(const LayerRect &rect);
-  LayerRect GetIntersection(const LayerRect &rect1, const LayerRect &rect2);
-  void LogRect(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
-  void NormalizeRect(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect);
-
+  bool IsValid(const LayerRect &rect);
+  bool IsCongruent(const LayerRect &rect1, const LayerRect &rect2);
+  void Log(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
+  void Normalize(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect);
+  LayerRect Union(const LayerRect &rect1, const LayerRect &rect2);
+  LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2);
+  LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2);
+  LayerRect Reposition(const LayerRect &rect1, const int &x_offset, const int &y_offset);
 }  // namespace sde
 
 #endif  // __RECT_H__
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index cc58465..1ca7c16 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -80,6 +80,8 @@
     destroy_strategy_intf_ = StrategyDefault::DestroyStrategyInterface;
   }
 
+  hw_res_info_ = hw_res_info;
+
   return error;
 }
 
@@ -96,7 +98,7 @@
 }
 
 DisplayError CompManager::RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
-                                          Handle *display_ctx) {
+                                          const HWPanelInfo &hw_panel_info, Handle *display_ctx) {
   SCOPE_LOCK(locker_);
 
   DisplayError error = kErrorNone;
@@ -106,7 +108,7 @@
     return kErrorMemory;
   }
 
-  if (create_strategy_intf_(STRATEGY_VERSION_TAG, type,
+  if (create_strategy_intf_(STRATEGY_VERSION_TAG, type, &hw_res_info_, &hw_panel_info,
                             &display_comp_ctx->strategy_intf) != kErrorNone) {
     DLOGW("Unable to create strategy interface");
     delete display_comp_ctx;
@@ -114,7 +116,8 @@
     return kErrorUndefined;
   }
 
-  error = res_mgr_.RegisterDisplay(type, attributes, &display_comp_ctx->display_resource_ctx);
+  error = res_mgr_.RegisterDisplay(type, attributes, hw_panel_info,
+                                   &display_comp_ctx->display_resource_ctx);
   if (error != kErrorNone) {
     destroy_strategy_intf_(display_comp_ctx->strategy_intf);
     delete display_comp_ctx;
@@ -170,8 +173,8 @@
 
   constraints->safe_mode = safe_mode_;
 
-  // Limit 2 layer SDE Comp on HDMI
-  if (display_comp_ctx->display_type == kHDMI) {
+  // Limit 2 layer SDE Comp on HDMI/Virtual
+  if (display_comp_ctx->display_type != kPrimary) {
     constraints->max_layers = 2;
   }
 
@@ -180,7 +183,7 @@
     constraints->safe_mode = true;
   }
 
-  if (display_comp_ctx->idle_fallback) {
+  if (display_comp_ctx->idle_fallback || display_comp_ctx->fallback_) {
     constraints->safe_mode = true;
   }
 }
@@ -318,6 +321,19 @@
   return false;
 }
 
+void CompManager::ProcessThermalEvent(Handle display_ctx, int64_t thermal_level) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+          reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (thermal_level >= kMaxThermalLevel) {
+    display_comp_ctx->fallback_ = true;
+  } else {
+    display_comp_ctx->fallback_ = false;
+  }
+}
+
 DisplayError CompManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
   SCOPE_LOCK(locker_);
 
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index 0a21ee0..c445418 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -40,7 +40,7 @@
                     BufferSyncHandler *buffer_sync_handler_);
   DisplayError Deinit();
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
-                               Handle *res_mgr_hnd);
+                               const HWPanelInfo &hw_panel_info, Handle *res_mgr_hnd);
   DisplayError UnregisterDisplay(Handle res_mgr_hnd);
   void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
@@ -48,12 +48,15 @@
   DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
   bool ProcessIdleTimeout(Handle display_ctx);
+  void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
   DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
 
  private:
+  static const int kMaxThermalLevel = 3;
+
   void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
 
   struct DisplayCompositionContext {
@@ -65,10 +68,12 @@
     uint32_t remaining_strategies;
     bool idle_fallback;
     bool handle_idle_timeout;
+    bool fallback_;
 
     DisplayCompositionContext()
       : display_resource_ctx(NULL), display_type(kPrimary), max_strategies(0),
-        remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true) { }
+        remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true),
+        fallback_(false) { }
   };
 
   Locker locker_;
@@ -81,6 +86,7 @@
   bool safe_mode_;                      // Flag to notify all displays to be in resource crunch
                                         // mode, where strategy manager chooses the best strategy
                                         // that uses optimal number of pipes for each display
+  HWResourceInfo hw_res_info_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index e58b4f8..a70a7c9 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -74,7 +74,7 @@
   }
 
   error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[active_mode_index_],
-                                        &display_comp_ctx_);
+                                         hw_panel_info_, &display_comp_ctx_);
   if (error != kErrorNone) {
     goto CleanupOnError;
   }
@@ -327,7 +327,8 @@
     comp_manager_->UnregisterDisplay(display_comp_ctx_);
   }
 
-  error = comp_manager_->RegisterDisplay(display_type_, display_attributes, &display_comp_ctx_);
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes, hw_panel_info_,
+                                         &display_comp_ctx_);
   if (error != kErrorNone) {
     return error;
   }
@@ -355,7 +356,7 @@
     comp_manager_->UnregisterDisplay(display_comp_ctx_);
   }
 
-  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[index],
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[index], hw_panel_info_,
                                          &display_comp_ctx_);
 
   return error;
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index 6f705f7..1dcd05b 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -166,7 +166,7 @@
 void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
   SCOPE_LOCK(locker_);
   // Idle fallback feature is supported only for video mode panel.
-  if (hw_panel_info_.mode == kModeCommand) {
+  if (hw_panel_info_.mode == kModeVideo) {
     hw_primary_intf_->SetIdleTimeoutMs(timeout_ms);
   }
 }
@@ -243,5 +243,10 @@
   }
 }
 
+void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
+  SCOPE_LOCK(locker_);
+  comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 8ce4f28..da84fe6 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -61,6 +61,7 @@
   virtual DisplayError VSync(int64_t timestamp);
   virtual DisplayError Blank(bool blank);
   virtual void IdleTimeout();
+  virtual void ThermalEvent(int64_t thermal_level);
 
  private:
   Locker locker_;
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
index 07d9e4d..c1dc99d 100644
--- a/displayengine/libs/core/fb/hw_device.h
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -69,7 +69,7 @@
 
   static const int kMaxStringLength = 1024;
   static const int kNumPhysicalDisplays = 2;
-  static const int kNumDisplayEvents = 3;
+  static const int kNumDisplayEvents = 4;
 
   void DumpLayerCommit(mdp_layer_commit &layer_commit);
   DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
diff --git a/displayengine/libs/core/fb/hw_hdmi.cpp b/displayengine/libs/core/fb/hw_hdmi.cpp
index bc97cf6..d45a620 100644
--- a/displayengine/libs/core/fb/hw_hdmi.cpp
+++ b/displayengine/libs/core/fb/hw_hdmi.cpp
@@ -222,6 +222,8 @@
   display_attributes->y_pixels = timing_mode->active_v;
   display_attributes->v_total = timing_mode->active_v + timing_mode->front_porch_v +
       timing_mode->back_porch_v + timing_mode->pulse_width_v;
+  display_attributes->h_total = timing_mode->active_h + timing_mode->front_porch_h +
+      timing_mode->back_porch_h + timing_mode->pulse_width_h;
   display_attributes->x_dpi = 0;
   display_attributes->y_dpi = 0;
   display_attributes->fps = FLOAT(timing_mode->refresh_rate) / 1000.0f;
diff --git a/displayengine/libs/core/fb/hw_primary.cpp b/displayengine/libs/core/fb/hw_primary.cpp
index 3b22054..33f28bb 100644
--- a/displayengine/libs/core/fb/hw_primary.cpp
+++ b/displayengine/libs/core/fb/hw_primary.cpp
@@ -75,7 +75,8 @@
   DisplayError error = kErrorNone;
   char node_path[kMaxStringLength] = {0};
   char data[kMaxStringLength] = {0};
-  const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify"};
+  const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify",
+                                              "msm_fb_thermal_level"};
 
   error = HWDevice::Init();
   if (error != kErrorNone) {
@@ -190,6 +191,8 @@
   display_attributes->y_pixels = var_screeninfo.yres;
   display_attributes->v_total = var_screeninfo.yres + var_screeninfo.lower_margin +
       var_screeninfo.upper_margin + var_screeninfo.vsync_len;
+  display_attributes->h_total = var_screeninfo.xres + var_screeninfo.right_margin +
+      var_screeninfo.left_margin + var_screeninfo.hsync_len;
   display_attributes->x_dpi =
       (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
   display_attributes->y_dpi =
@@ -285,7 +288,8 @@
   typedef void (HWPrimary::*EventHandler)(char*);
   EventHandler event_handler[kNumDisplayEvents] = { &HWPrimary::HandleVSync,
                                                     &HWPrimary::HandleBlank,
-                                                    &HWPrimary::HandleIdleTimeout };
+                                                    &HWPrimary::HandleIdleTimeout,
+                                                    &HWPrimary::HandleThermal };
 
   while (!exit_threads_) {
     int error = poll_(poll_fds_, kNumDisplayEvents, -1);
@@ -330,6 +334,17 @@
   event_handler_->IdleTimeout();
 }
 
+void HWPrimary::HandleThermal(char *data) {
+  int64_t thermal_level = 0;
+  if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
+    thermal_level = strtoull(data + strlen("thermal_level="), NULL, 0);
+  }
+
+  DLOGI("Received thermal notification with thermal level = %d",thermal_level);
+
+  event_handler_->ThermalEvent(thermal_level);
+}
+
 void HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
   char node_path[kMaxStringLength] = {0};
 
diff --git a/displayengine/libs/core/fb/hw_primary.h b/displayengine/libs/core/fb/hw_primary.h
index b008c92..8d61d74 100644
--- a/displayengine/libs/core/fb/hw_primary.h
+++ b/displayengine/libs/core/fb/hw_primary.h
@@ -68,6 +68,7 @@
   void HandleVSync(char *data);
   void HandleBlank(char *data);
   void HandleIdleTimeout(char *data);
+  void HandleThermal(char *data);
 
   pollfd poll_fds_[kNumDisplayEvents];
   pthread_t event_thread_;
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index e8e0c63..8cd608e 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -123,6 +123,7 @@
   virtual DisplayError VSync(int64_t timestamp) = 0;
   virtual DisplayError Blank(bool blank) = 0;
   virtual void IdleTimeout() = 0;
+  virtual void ThermalEvent(int64_t thermal_level) = 0;
  protected:
   virtual ~HWEventHandler() { }
 };
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 4624a35..ecd8ef1 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -168,7 +168,7 @@
   scissor.bottom = FLOAT(display_attributes.y_pixels);
   bool crop_right_valid = false;
 
-  if (IsValidRect(scissor)) {
+  if (IsValid(scissor)) {
     crop_right_valid = CalculateCropRects(scissor, transform, &crop_right, &dst_right);
   }
 
@@ -240,8 +240,8 @@
     float rot_scale = 1.0f;
     if (!IsValidDimension(layer.src_rect, layer.dst_rect)) {
       DLOGV_IF(kTagResources, "Input is invalid");
-      LogRect(kTagResources, "input layer src_rect", layer.src_rect);
-      LogRect(kTagResources, "input layer dst_rect", layer.dst_rect);
+      Log(kTagResources, "input layer src_rect", layer.src_rect);
+      Log(kTagResources, "input layer dst_rect", layer.dst_rect);
       return kErrorNotSupported;
     }
 
@@ -265,7 +265,7 @@
     uint32_t align_x, align_y;
     GetAlignFactor(layer.input_buffer->format, &align_x, &align_y);
     if (align_x > 1 || align_y > 1) {
-      NormalizeRect(align_x, align_y, &src_rect);
+      Normalize(align_x, align_y, &src_rect);
     }
 
     if (ValidateScaling(layer, src_rect, dst_rect, &rot_scale)) {
@@ -304,21 +304,21 @@
 
     DLOGV_IF(kTagResources, "==== layer = %d, left pipe valid = %d ====",
              i, layer_config->left_pipe.valid);
-    LogRect(kTagResources, "input layer src_rect", layer.src_rect);
-    LogRect(kTagResources, "input layer dst_rect", layer.dst_rect);
+    Log(kTagResources, "input layer src_rect", layer.src_rect);
+    Log(kTagResources, "input layer dst_rect", layer.dst_rect);
     for (uint32_t k = 0; k < layer_config->num_rotate; k++) {
       DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f", k, rot_scale);
-      LogRect(kTagResources, "rotate src", layer_config->rotates[k].src_roi);
-      LogRect(kTagResources, "rotate dst", layer_config->rotates[k].dst_roi);
+      Log(kTagResources, "rotate src", layer_config->rotates[k].src_roi);
+      Log(kTagResources, "rotate dst", layer_config->rotates[k].dst_roi);
     }
 
-    LogRect(kTagResources, "cropped src_rect", src_rect);
-    LogRect(kTagResources, "cropped dst_rect", dst_rect);
-    LogRect(kTagResources, "left pipe src", layer_config->left_pipe.src_roi);
-    LogRect(kTagResources, "left pipe dst", layer_config->left_pipe.dst_roi);
+    Log(kTagResources, "cropped src_rect", src_rect);
+    Log(kTagResources, "cropped dst_rect", dst_rect);
+    Log(kTagResources, "left pipe src", layer_config->left_pipe.src_roi);
+    Log(kTagResources, "left pipe dst", layer_config->left_pipe.dst_roi);
     if (hw_layers->config[i].right_pipe.valid) {
-      LogRect(kTagResources, "right pipe src", layer_config->right_pipe.src_roi);
-      LogRect(kTagResources, "right pipe dst", layer_config->right_pipe.dst_roi);
+      Log(kTagResources, "right pipe src", layer_config->right_pipe.src_roi);
+      Log(kTagResources, "right pipe dst", layer_config->right_pipe.dst_roi);
     }
     // set z_order, left_pipe should always be valid
     left_pipe.z_order = z_order;
@@ -507,9 +507,9 @@
   crop_top += crop_height * top_cut_ratio;
   crop_right -= crop_width * right_cut_ratio;
   crop_bottom -= crop_height * bottom_cut_ratio;
-  NormalizeRect(1, 1, crop);
-  NormalizeRect(1, 1, dst);
-  if (IsValidRect(*crop) && IsValidRect(*dst))
+  Normalize(1, 1, crop);
+  Normalize(1, 1, dst);
+  if (IsValid(*crop) && IsValid(*dst))
     return true;
   else
     return false;
@@ -612,12 +612,12 @@
   // 2. Normalize source and destination rect of a layer to multiple of 1.
   // TODO(user) Check buffer format and check if rotate is involved.
 
-  NormalizeRect(align_x, align_y, &left_pipe->src_roi);
-  NormalizeRect(1, 1, &left_pipe->dst_roi);
+  Normalize(align_x, align_y, &left_pipe->src_roi);
+  Normalize(1, 1, &left_pipe->dst_roi);
 
   if (right_pipe->valid) {
-    NormalizeRect(align_x, align_y, &right_pipe->src_roi);
-    NormalizeRect(1, 1, &right_pipe->dst_roi);
+    Normalize(align_x, align_y, &right_pipe->src_roi);
+    Normalize(1, 1, &right_pipe->dst_roi);
   }
 
   if (right_pipe->valid) {
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 3573e78..4101fc8 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -122,6 +122,8 @@
 #ifdef USES_SCALAR
   ScalarHelper::GetInstance()->Init();
 #endif
+
+  max_system_bw_ = FLOAT(hw_res_info_.max_bandwidth_high);
   return kErrorNone;
 }
 
@@ -133,7 +135,7 @@
 }
 
 DisplayError ResManager::RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
-                                         Handle *display_ctx) {
+                                         const HWPanelInfo &hw_panel_info, Handle *display_ctx) {
   DisplayError error = kErrorNone;
 
   HWBlockType hw_block_id = kHWBlockMax;
@@ -170,6 +172,7 @@
     return kErrorMemory;
   }
 
+  display_resource_ctx->hw_panel_info_ = hw_panel_info;
   display_resource_ctx->buffer_manager = new BufferManager(buffer_allocator_, buffer_sync_handler_);
   if (display_resource_ctx->buffer_manager == NULL) {
     delete display_resource_ctx;
@@ -445,7 +448,9 @@
     right_pipe_bw[i] = right_pipe->valid ? GetPipeBw(display_ctx, right_pipe, bpp) : 0;
 
     if ((left_pipe_bw[i] > max_pipe_bw) || (right_pipe_bw[i] > max_pipe_bw)) {
-      DLOGV_IF(kTagResources, "Pipe bandwidth exceeds limit for layer index = %d", i);
+      DLOGV_IF(kTagResources, "Pipe bandwidth exceeds limit for layer index=%d !" \
+               " left_pipe_bw=%f, right_pipe_bw=%f, max_pipe_bw=%f",
+               i, left_pipe_bw[i], right_pipe_bw[i], max_pipe_bw);
       return false;
     }
 
@@ -466,9 +471,14 @@
     last_primary_bw_ = left_mixer_bw + right_mixer_bw;
   }
 
-  // If system has Video mode panel, use max_bandwidth_low, else use max_bandwidth_high
-  if ((display_bw + bw_claimed_) > (hw_res_info_.max_bandwidth_low / 1000000)) {
-    DLOGV_IF(kTagResources, "Overlap bandwidth exceeds limit!");
+  // If system has Video mode panel, then bw limit is max_bandwidth_low
+  if (display_ctx->hw_panel_info_.mode == kModeVideo) {
+    max_system_bw_ = FLOAT(hw_res_info_.max_bandwidth_low);
+  }
+
+  if ((display_bw + bw_claimed_) > (max_system_bw_ / 1000000)) {
+    DLOGV_IF(kTagResources, "Overlap bandwidth: %f exceeds system limit: %f (GBps)!",
+             (display_bw + bw_claimed_), (max_system_bw_ / 1000000));
     return false;
   }
 
@@ -480,7 +490,8 @@
 
   // Apply fudge factor to consider in-efficieny
   if ((system_clk * hw_res_info_.clk_fudge_factor) > max_sde_clk) {
-    DLOGV_IF(kTagResources, "Clock requirement exceeds limit!");
+    DLOGV_IF(kTagResources, "Clock requirement: %f exceeds system limit: %f (MHz)!",
+             (system_clk * hw_res_info_.clk_fudge_factor), max_sde_clk);
     return false;
   }
 
@@ -512,6 +523,15 @@
   // (v_total / v_active) * (v_active / dst_h)
   bw *= FLOAT(display_attributes.v_total) / dst_h;
 
+  // Bandwidth is the rate at which data needs to be fetched from source to MDP (bytes/time).
+  // On Video mode panel, there is no transfer of data from MDP to panel in horizontal blanking
+  // time (hBP + hFP + hPW). So MDP gets this extra time to fetch data from source. But on the
+  // Command mode panel, data gets transferred from MDP to panel during blanking time as well,
+  // which means MDP needs to fetch the data faster. So pipe bandwidth needs to be adjusted.
+  if (display_ctx->hw_panel_info_.mode == kModeCommand) {
+    bw *= FLOAT(display_attributes.h_total) / FLOAT(display_attributes.x_pixels);
+  }
+
   // Bandwidth in GBps
   return (bw / 1000000000.0f);
 }
@@ -1119,7 +1139,7 @@
   // Initialize the output format with input format by default.
   *output_format = input_format;
 
-  switch(input_format) {
+  switch (input_format) {
   case kFormatARGB8888:
   case kFormatRGBA8888:
     if (is_opaque) {
@@ -1182,8 +1202,9 @@
     }
   }
 
-  DLOGV_IF(kTagResources, "Input format %x, Output format = %x, rot90 %d ubwc %d downscale %d",
-           input_format, *output_format, rot90, hw_res_info_.has_ubwc, downscale);
+  DLOGV_IF(kTagResources, "Input format = %x, Output format = %x, rot90 = %d, ubwc = %d,"
+           "downscale = %d", input_format, *output_format, rot90, hw_res_info_.has_ubwc,
+           downscale);
 
   return;
 }
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index c293453..1653c0a 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -42,7 +42,7 @@
                     BufferSyncHandler *buffer_sync_handler);
   DisplayError Deinit();
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
-                               Handle *display_ctx);
+                               const HWPanelInfo &hw_panel_info, Handle *display_ctx);
   DisplayError UnregisterDisplay(Handle display_ctx);
   DisplayError Start(Handle display_ctx);
   DisplayError Stop(Handle display_ctx);
@@ -120,6 +120,7 @@
     BufferManager *buffer_manager;
     DisplayType display_type;
     HWBlockType hw_block_id;
+    HWPanelInfo hw_panel_info_;
     uint64_t frame_count;
     int32_t session_id;  // applicable for virtual display sessions only
     uint32_t rotate_count;
@@ -224,6 +225,7 @@
   float bw_claimed_;  // Bandwidth claimed by other display
   float clk_claimed_;  // Clock claimed by other display
   float last_primary_bw_;
+  float max_system_bw_;
   uint32_t virtual_count_;
   struct HWRotator rotators_[kMaxNumRotator];
   BufferAllocator *buffer_allocator_;
diff --git a/displayengine/libs/core/strategy_default.cpp b/displayengine/libs/core/strategy_default.cpp
index e3270b7..48fc79d 100644
--- a/displayengine/libs/core/strategy_default.cpp
+++ b/displayengine/libs/core/strategy_default.cpp
@@ -35,6 +35,8 @@
 }
 
 DisplayError StrategyDefault::CreateStrategyInterface(uint16_t version, DisplayType type,
+                                                      const HWResourceInfo *hw_resource_info,
+                                                      const HWPanelInfo *hw_panel_info,
                                                       StrategyInterface **interface) {
   StrategyDefault *strategy_default  = new StrategyDefault();
 
diff --git a/displayengine/libs/core/strategy_default.h b/displayengine/libs/core/strategy_default.h
index 2ba19f8..7b6f594 100644
--- a/displayengine/libs/core/strategy_default.h
+++ b/displayengine/libs/core/strategy_default.h
@@ -35,6 +35,8 @@
   StrategyDefault();
 
   static DisplayError CreateStrategyInterface(uint16_t version, DisplayType type,
+                                              const HWResourceInfo *hw_resource_info,
+                                              const HWPanelInfo *hw_panel_info,
                                               StrategyInterface **interface);
   static DisplayError DestroyStrategyInterface(StrategyInterface *interface);
 
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index cd21c8a..8d7e94a 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -27,6 +27,7 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#include <math.h>
 #include <errno.h>
 #include <gralloc_priv.h>
 #include <utils/constants.h>
@@ -571,10 +572,10 @@
 }
 
 void HWCDisplay::SetRect(const hwc_frect_t &source, LayerRect *target) {
-  target->left = source.left;
-  target->top = source.top;
-  target->right = source.right;
-  target->bottom = source.bottom;
+  target->left = floorf(source.left);
+  target->top = floorf(source.top);
+  target->right = ceilf(source.right);
+  target->bottom = ceilf(source.bottom);
 }
 
 void HWCDisplay::SetComposition(const int32_t &source, LayerComposition *target) {
diff --git a/displayengine/libs/utils/debug_android.cpp b/displayengine/libs/utils/debug_android.cpp
index 96339df..77c82b0 100644
--- a/displayengine/libs/utils/debug_android.cpp
+++ b/displayengine/libs/utils/debug_android.cpp
@@ -89,5 +89,15 @@
   return false;
 }
 
+// This property serves to disable/enable partial update
+bool Debug::IsPartialUpdate() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("sde.hwc.partial_update", property, NULL) > 0) {
+    return (atoi(property) ? 1 : true, false);
+  }
+
+  return false;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/utils/rect.cpp b/displayengine/libs/utils/rect.cpp
index 8dfd7dd..9b05951 100644
--- a/displayengine/libs/utils/rect.cpp
+++ b/displayengine/libs/utils/rect.cpp
@@ -35,15 +35,33 @@
 
 namespace sde {
 
-bool IsValidRect(const LayerRect &rect) {
+bool IsValid(const LayerRect &rect) {
   return ((rect.bottom > rect.top) && (rect.right > rect.left));
 }
 
+bool IsCongruent(const LayerRect &rect1, const LayerRect &rect2) {
+  return ((rect1.left == rect2.left) &&
+          (rect1.top == rect2.top) &&
+          (rect1.right == rect2.right) &&
+          (rect1.bottom == rect2.bottom));
+}
 
-LayerRect GetIntersection(const LayerRect &rect1, const LayerRect &rect2) {
+void Log(DebugTag debug_tag, const char *prefix, const LayerRect &roi) {
+  DLOGV_IF(debug_tag, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
+           prefix, roi.left, roi.top, roi.right, roi.bottom);
+}
+
+void Normalize(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect) {
+    rect->left = ROUND_UP_ALIGN_UP(rect->left, align_x);
+    rect->right = ROUND_UP_ALIGN_DOWN(rect->right, align_x);
+    rect->top = ROUND_UP_ALIGN_UP(rect->top, align_y);
+    rect->bottom = ROUND_UP_ALIGN_DOWN(rect->bottom, align_y);
+}
+
+LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2) {
   LayerRect res;
 
-  if (!IsValidRect(rect1) || !IsValidRect(rect2)) {
+  if (!IsValid(rect1) || !IsValid(rect2)) {
     return LayerRect();
   }
 
@@ -52,23 +70,72 @@
   res.right = MIN(rect1.right, rect2.right);
   res.bottom = MIN(rect1.bottom, rect2.bottom);
 
-  if (!IsValidRect(res)) {
+  if (!IsValid(res)) {
     return LayerRect();
   }
 
   return res;
 }
 
-void LogRect(DebugTag debug_tag, const char *prefix, const LayerRect &roi) {
-  DLOGV_IF(debug_tag, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
-           prefix, roi.left, roi.top, roi.right, roi.bottom);
+LayerRect Reposition(const LayerRect &rect, const int &x_offset, const int &y_offset) {
+  LayerRect res;
+
+  if (!IsValid(rect)) {
+    return LayerRect();
+  }
+
+  res.left = rect.left + FLOAT(x_offset);
+  res.top = rect.top + FLOAT(y_offset);
+  res.right = rect.right + FLOAT(x_offset);
+  res.bottom = rect.bottom + FLOAT(y_offset);
+
+  return res;
 }
 
-void NormalizeRect(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect) {
-  rect->left = ROUND_UP_ALIGN_UP(rect->left, align_x);
-  rect->right = ROUND_UP_ALIGN_DOWN(rect->right, align_x);
-  rect->top = ROUND_UP_ALIGN_UP(rect->top, align_y);
-  rect->bottom = ROUND_UP_ALIGN_DOWN(rect->bottom, align_y);
+// Not a geometrical rect deduction. Deducts rect2 from rect1 only if it results a single rect
+LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2) {
+  LayerRect res;
+
+  res = rect1;
+
+  if ((rect1.left == rect2.left) && (rect1.right == rect2.right)) {
+    if ((rect1.top == rect2.top) && (rect2.bottom <= rect1.bottom)) {
+      res.top = rect2.bottom;
+    } else if ((rect1.bottom == rect2.bottom) && (rect2.top >= rect1.top)) {
+      res.bottom = rect2.top;
+    }
+  } else if ((rect1.top == rect2.top) && (rect1.bottom == rect2.bottom)) {
+    if ((rect1.left == rect2.left) && (rect2.right <= rect1.right)) {
+      res.left = rect2.right;
+    } else if ((rect1.right == rect2.right) && (rect2.left >= rect1.left)) {
+      res.right = rect2.left;
+    }
+  }
+
+  return res;
+}
+
+LayerRect Union(const LayerRect &rect1, const LayerRect &rect2) {
+  LayerRect res;
+
+  if (!IsValid(rect1) && !IsValid(rect2)) {
+    return LayerRect();
+  }
+
+  if(!IsValid(rect1)){
+    return rect2;
+  }
+
+  if(!IsValid(rect2)){
+    return rect1;
+  }
+
+  res.left = MIN(rect1.left, rect2.left);
+  res.top = MIN(rect1.top, rect2.top);
+  res.right = MAX(rect1.right, rect2.right);
+  res.bottom = MAX(rect1.bottom, rect2.bottom);
+
+  return res;
 }
 
 }  // namespace sde
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 8b38952..acac5b4 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -328,18 +328,20 @@
                 native_handle_t** handle = va_arg(args, native_handle_t**);
                 private_handle_t* hnd = (private_handle_t*)native_handle_create(
                     private_handle_t::sNumFds, private_handle_t::sNumInts());
-                hnd->magic = private_handle_t::sMagic;
-                hnd->fd = fd;
-                hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
-                hnd->size = size;
-                hnd->offset = offset;
-                hnd->base = uint64_t(base) + offset;
-                hnd->gpuaddr = 0;
-                hnd->width = width;
-                hnd->height = height;
-                hnd->format = format;
-                *handle = (native_handle_t *)hnd;
-                res = 0;
+                if (hnd) {
+                  hnd->magic = private_handle_t::sMagic;
+                  hnd->fd = fd;
+                  hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
+                  hnd->size = size;
+                  hnd->offset = offset;
+                  hnd->base = uint64_t(base) + offset;
+                  hnd->gpuaddr = 0;
+                  hnd->width = width;
+                  hnd->height = height;
+                  hnd->format = format;
+                  *handle = (native_handle_t *)hnd;
+                  res = 0;
+                }
                 break;
 
             }
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index d7b6278..f44a707 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -1200,12 +1200,6 @@
 }
 
 void CopyBit::setReleaseFd(int fd) {
-    if(mRelFd[mCurRenderBufferIndex] >=0)
-        close(mRelFd[mCurRenderBufferIndex]);
-    mRelFd[mCurRenderBufferIndex] = dup(fd);
-}
-
-void CopyBit::setReleaseFdSync(int fd) {
     if (mRelFd[mCurRenderBufferIndex] >=0) {
         int ret = -1;
         ret = sync_wait(mRelFd[mCurRenderBufferIndex], 1000);
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index b67e1b8..993c790 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -51,8 +51,6 @@
 
     void setReleaseFd(int fd);
 
-    void setReleaseFdSync(int fd);
-
     bool prepareOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
 
     int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 087fe1e..fdd7f0f 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -924,6 +924,15 @@
         }
     }
 
+    if(!mDpy && isSecondaryConnected(ctx) &&
+           (qdutils::MDPVersion::getInstance().is8x16() ||
+            qdutils::MDPVersion::getInstance().is8x26() ||
+            qdutils::MDPVersion::getInstance().is8x39()) &&
+           isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
+        ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
+        return false;
+    }
+
     mCurrentFrame.fbCount = 0;
     memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
            sizeof(mCurrentFrame.isFBComposed));
@@ -982,6 +991,15 @@
         }
     }
 
+    if(!mDpy && isSecondaryConnected(ctx) &&
+           (qdutils::MDPVersion::getInstance().is8x16() ||
+            qdutils::MDPVersion::getInstance().is8x26() ||
+            qdutils::MDPVersion::getInstance().is8x39()) &&
+           isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
+        ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
+        return false;
+    }
+
     /* We cannot use this composition mode, if:
      1. A below layer needs scaling.
      2. Overlap is not peripheral to display.
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 8efe025..2f5aed0 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1594,34 +1594,9 @@
     }
 }
 
-int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
-        int fd) {
+void hwc_sync_rotator(hwc_context_t *ctx, hwc_display_contents_1_t* list,
+        int dpy) {
     ATRACE_CALL();
-    int ret = 0;
-    int acquireFd[MAX_NUM_APP_LAYERS];
-    int count = 0;
-    int releaseFd = -1;
-    int retireFd = -1;
-    int fbFd = -1;
-    bool swapzero = false;
-
-    struct mdp_buf_sync data;
-    memset(&data, 0, sizeof(data));
-    data.acq_fen_fd = acquireFd;
-    data.rel_fen_fd = &releaseFd;
-    data.retire_fen_fd = &retireFd;
-    data.flags = MDP_BUF_SYNC_FLAG_RETIRE_FENCE;
-
-    char property[PROPERTY_VALUE_MAX];
-    if(property_get("debug.egl.swapinterval", property, "1") > 0) {
-        if(atoi(property) == 0)
-            swapzero = true;
-    }
-
-    bool isExtAnimating = false;
-    if(dpy)
-       isExtAnimating = ctx->listStats[dpy].isDisplayAnimating;
-
     //Send acquireFenceFds to rotator
     for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
         int rotFd = ctx->mRotMgr->getRotDevFd();
@@ -1641,7 +1616,7 @@
             rotData.acq_fen_fd_cnt = 1; //1 ioctl call per rot session
         }
         int ret = 0;
-        if(LIKELY(!swapzero) and (not ctx->mLayerRotMap[dpy]->isRotCached(i)))
+        if(not ctx->mLayerRotMap[dpy]->isRotCached(i))
             ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
 
         if(ret < 0) {
@@ -1659,58 +1634,61 @@
                     rotReleaseFd;
         }
     }
+}
+
+int hwc_sync_mdss(hwc_context_t *ctx, hwc_display_contents_1_t *list, int dpy,
+        bool isExtAnimating, int fd) {
+    ATRACE_CALL();
+    int ret = 0;
+    int acquireFd[MAX_NUM_APP_LAYERS];
+    int count = 0;
+    int releaseFd = -1;
+    int retireFd = -1;
+    int fbFd = ctx->dpyAttr[dpy].fd;
+
+    struct mdp_buf_sync data;
+    memset(&data, 0, sizeof(data));
+    data.acq_fen_fd = acquireFd;
+    data.rel_fen_fd = &releaseFd;
+    data.retire_fen_fd = &retireFd;
+    data.flags = MDP_BUF_SYNC_FLAG_RETIRE_FENCE;
 
     //Accumulate acquireFenceFds for MDP Overlays
     if(list->outbufAcquireFenceFd >= 0) {
         //Writeback output buffer
-        if(LIKELY(!swapzero) )
-            acquireFd[count++] = list->outbufAcquireFenceFd;
+        acquireFd[count++] = list->outbufAcquireFenceFd;
     }
 
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
         if(((isAbcInUse(ctx)== true ) ||
           (list->hwLayers[i].compositionType == HWC_OVERLAY)) &&
                         list->hwLayers[i].acquireFenceFd >= 0) {
-            if(LIKELY(!swapzero) ) {
-                // if ABC is enabled for more than one layer.
-                // renderBufIndexforABC will work as FB.Hence
-                // set the acquireFD from fd - which is coming from copybit
-                if(fd >= 0 && (isAbcInUse(ctx) == true)) {
-                    if(ctx->listStats[dpy].renderBufIndexforABC ==(int32_t)i)
-                        acquireFd[count++] = fd;
-                    else
-                        continue;
-                } else
-                    acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
-            }
+            // if ABC is enabled for more than one layer.
+            // renderBufIndexforABC will work as FB.Hence
+            // set the acquireFD from fd - which is coming from copybit
+            if(fd >= 0 && (isAbcInUse(ctx) == true)) {
+                if(ctx->listStats[dpy].renderBufIndexforABC ==(int32_t)i)
+                    acquireFd[count++] = fd;
+                else
+                    continue;
+            } else
+                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
         }
         if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
-            if(LIKELY(!swapzero) ) {
-                if(fd >= 0) {
-                    //set the acquireFD from fd - which is coming from c2d
-                    acquireFd[count++] = fd;
-                    // Buffer sync IOCTL should be async when using c2d fence is
-                    // used
-                    data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
-                } else if(list->hwLayers[i].acquireFenceFd >= 0)
-                    acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
-            }
+            if(fd >= 0) {
+                //set the acquireFD from fd - which is coming from c2d
+                acquireFd[count++] = fd;
+                // Buffer sync IOCTL should be async when using c2d fence
+                data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
+            } else if(list->hwLayers[i].acquireFenceFd >= 0)
+                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
         }
     }
 
-    if ((fd >= 0) && !dpy && ctx->mPtorInfo.isActive()) {
-        // Acquire c2d fence of Overlap render buffer
-        if(LIKELY(!swapzero) )
-            acquireFd[count++] = fd;
-    }
-
     data.acq_fen_fd_cnt = count;
-    fbFd = ctx->dpyAttr[dpy].fd;
 
     //Waits for acquire fences, returns a release fence
-    if(LIKELY(!swapzero)) {
-        ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
-    }
+    ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
 
     if(ret < 0) {
         ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed, err=%s",
@@ -1731,9 +1709,7 @@
 #endif
            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
             //Populate releaseFenceFds.
-            if(UNLIKELY(swapzero)) {
-                list->hwLayers[i].releaseFenceFd = -1;
-            } else if(isExtAnimating) {
+            if(isExtAnimating) {
                 // Release all the app layer fds immediately,
                 // if animation is in progress.
                 list->hwLayers[i].releaseFenceFd = -1;
@@ -1760,16 +1736,11 @@
         }
     }
 
-    if(fd >= 0) {
-        close(fd);
-        fd = -1;
-    }
-
     if (ctx->mCopyBit[dpy]) {
-        if (!dpy && ctx->mPtorInfo.isActive())
-            ctx->mCopyBit[dpy]->setReleaseFdSync(releaseFd);
-        else
+        if((!dpy && ctx->mPtorInfo.isActive()) or
+           ctx->mMDP.version < qdutils::MDP_V4_0) {
             ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+        }
     }
 
     //Signals when MDP finishes reading rotator buffers.
@@ -1777,11 +1748,59 @@
     close(releaseFd);
     releaseFd = -1;
 
-    if(UNLIKELY(swapzero)) {
-        list->retireFenceFd = -1;
-    } else {
-        list->retireFenceFd = retireFd;
+    list->retireFenceFd = retireFd;
+
+    return ret;
+}
+
+void hwc_sync_sz(hwc_context_t* ctx, hwc_display_contents_1_t* list, int dpy) {
+    ATRACE_CALL();
+    for(uint32_t i = 0; i < list->numHwLayers; i++) {
+        list->hwLayers[i].releaseFenceFd = -1;
     }
+
+    if (ctx->mCopyBit[dpy]) {
+        if((!dpy && ctx->mPtorInfo.isActive()) or
+           ctx->mMDP.version < qdutils::MDP_V4_0) {
+            ctx->mCopyBit[dpy]->setReleaseFd(-1);
+        }
+    }
+
+    ctx->mLayerRotMap[dpy]->setReleaseFd(-1);
+
+    list->retireFenceFd = -1;
+}
+
+int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
+        int fd) {
+    ATRACE_CALL();
+    int ret = 0;
+
+    bool isExtAnimating = false;
+    if(dpy)
+        isExtAnimating = ctx->listStats[dpy].isDisplayAnimating;
+
+    bool swapzero = false;
+    char property[PROPERTY_VALUE_MAX];
+    if(property_get("debug.egl.swapinterval", property, "1") > 0) {
+        if(atoi(property) == 0)
+            swapzero = true;
+    }
+
+    if(swapzero) {
+        hwc_sync_sz(ctx, list, dpy);
+    } else {
+        hwc_sync_rotator(ctx, list, dpy);
+        ret = hwc_sync_mdss(ctx, list, dpy,
+                            isExtAnimating, fd);
+    }
+
+    if(fd >= 0) {
+        close(fd);
+        fd = -1;
+    }
+
+
     return ret;
 }
 
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index f0f8e77..a74d59a 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -395,6 +395,17 @@
 //Close acquireFenceFds of all layers of incoming list
 void closeAcquireFds(hwc_display_contents_1_t* list);
 
+//Sync point impl if swapinterval is set to 0
+void hwc_sync_sz(hwc_context_t* ctx, hwc_display_contents_1_t* list, int dpy);
+
+//Sync point impl for rotator
+void hwc_sync_rotator(hwc_context_t *ctx, hwc_display_contents_1_t* list,
+        int dpy);
+
+//Sync point impl for mdss
+int hwc_sync_mdss(hwc_context_t *ctx, hwc_display_contents_1_t *list, int dpy,
+        bool isExtAnimating, int fd);
+
 //Sync point impl.
 int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
         int fd);