Merge "overlay: Reset display and mixer tags for unallocated pipes"
diff --git a/displayengine/include/core/dump_interface.h b/displayengine/include/core/dump_interface.h
index 674e60f..3a7d93d 100644
--- a/displayengine/include/core/dump_interface.h
+++ b/displayengine/include/core/dump_interface.h
@@ -47,17 +47,16 @@
     @details Client shall use this method to get current snapshot of display engine context as a
     formatted string for logging or dumping purposes.
 
-    @param[inout] buffer String buffer allocated by the client. Filled with dump information upon
-    return.
+    @param[inout] buffer String buffer allocated by the client. Filled with null terminated dump
+    information upon return.
     @param[in] length Length of the string buffer. Length shall be offset adjusted if any.
-    @param[in] filled Number of bytes filled into the string buffer.
 
     @return \link DisplayError \endlink
 
     @warning Client shall ensure that this interface is not used while a device is being either
     created or destroyed through display core.
   */
-  static DisplayError GetDump(uint8_t *buffer, uint32_t length, uint32_t *filled);
+  static DisplayError GetDump(char *buffer, uint32_t length);
 
  protected:
   virtual ~DumpInterface() { }
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
index e6dcf1c..421ab87 100644
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -106,7 +106,8 @@
 struct LayerBufferFlags {
   uint64_t secure : 1;  //!< This flag shall be set by client to indicate that the buffer need
                         //!< to be handled securely.
-
+  uint64_t video  : 1;  //!< This flag shall be set by client to indicate that the buffer is
+                        //!< video/ui buffer
   LayerBufferFlags() : secure(0) { }
 };
 
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
index fddfa8e..74c1960 100644
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -93,10 +93,13 @@
   @sa LayerBuffer
 */
 struct LayerFlags {
-  uint64_t skip : 1;  //!< This flag shall be set by client to indicate that this layer will be
-                      //!< handled by GPU. Device Device will not consider it for composition.
-
-  LayerFlags() : skip(0) { }
+  uint64_t skip : 1;      //!< This flag shall be set by client to indicate that this layer will be
+                          //!< handled by GPU. Display Device will not consider it for composition.
+  uint64_t updating : 1;  //!< This flag shall be set by client to indicate that this is updating/
+                          //!< non-updating. so strategy manager will mark them for SDE/GPU
+                          //!< composition respectively when the layer stack qualifies for cache
+                          //!< based composition.
+  LayerFlags() : skip(0), updating(0) { }
 };
 
 /*! @brief This structure defines flags associated with a layer stack. The 1-bit flag can be set to
@@ -108,8 +111,14 @@
   uint64_t geometry_changed : 1;  //!< This flag shall be set by client to indicate that the layer
                                   //!< set passed to Prepare() has changed by more than just the
                                   //!< buffer handles and acquire fences.
+  uint64_t skip_present : 1;      //!< This flag will be set to true, if the current layer stack
+                                  //!< contains skip layers
+  uint64_t video_present : 1;     //!< This flag will be set to true, if current layer stack
+                                  //!< contains video
+  uint64_t secure_present : 1;    //!< This flag will be set to true, if the current layer stack
+                                  //!< contains secure layers
 
-  LayerStackFlags() : geometry_changed(0) { }
+  LayerStackFlags() : geometry_changed(0), skip_present(0), video_present(0), secure_present(0) { }
 };
 
 /*! @brief This structure defines a rectanglular area inside a display layer.
diff --git a/displayengine/include/private/strategy_interface.h b/displayengine/include/private/strategy_interface.h
index 7050929..23dea8e 100644
--- a/displayengine/include/private/strategy_interface.h
+++ b/displayengine/include/private/strategy_interface.h
@@ -67,7 +67,7 @@
 
 /*! @brief Maximum number of layers that can be handled by hardware in a given layer stack.
 */
-const int kNumLayersMax = 16;
+const int kMaxSDELayers = 16;
 
 /*! @brief This structure defines constraints and device properties that shall be considered for
     deciding a composition strategy.
@@ -75,11 +75,13 @@
     @sa GetNextStrategy
 */
 struct StrategyConstraints {
-  bool gpu_only;          //!< Select GPU only composition for this layer stack.
+  bool safe_mode;         //!< In this mode, strategy manager chooses the composition strategy
+                          //!< that requires minimum number of pipe for the current frame. i.e.,
+                          //!< video only composition, secure only composition or GPU composition
   uint32_t max_layers;    //!< Maximum number of layers that shall be programmed on hardware for the
                           //!< given layer stack.
 
-  StrategyConstraints() : gpu_only(false), max_layers(kNumLayersMax) { }
+  StrategyConstraints() : safe_mode(false), max_layers(kMaxSDELayers) { }
 };
 
 /*! @brief Flag to denote that GPU composition is performed for the given layer stack.
@@ -94,7 +96,7 @@
 struct HWLayersInfo {
   LayerStack *stack;        //!< Input layer stack. Set by the caller.
 
-  uint32_t index[kNumLayersMax];
+  uint32_t index[kMaxSDELayers];
                             //!< Indexes of the layers from the layer stack which need to be
                             //!< programmed on hardware.
   uint32_t count;           //!< Total number of layers which need to be set on hardware.
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index 4b18ed6..7d7a39c 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -43,6 +43,9 @@
 
 #define ROUND_UP(number, step) ((((number) + ((step) - 1)) / (step)) * (step))
 
+#define SET_BIT(value, bit) ((value) | (1 << (bit)))
+#define CLEAR_BIT(value, bit) ((value) & (~(1 << (bit))))
+
 namespace sde {
 
   const int kThreadPriorityUrgent = -9;
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
index 10d5ea6..0691dfc 100644
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -46,9 +46,9 @@
 namespace sde {
 
 enum LogTag {
-  kTagNone = 0,   //!< Log tag name is not specified.
-  kTagCore,       //!< Log is tagged for display core.
-  kTagStrategy,   //!< Log is tagged for composition strategy.
+  kTagNone = 0,   // Log tag name is not specified.
+  kTagCore,       // Log is tagged for display core.
+  kTagStrategy,   // Log is tagged for composition strategy.
 };
 
 class Debug {
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 560db52..42a28c2 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -34,7 +34,8 @@
 
 namespace sde {
 
-CompManager::CompManager() : strategy_lib_(NULL), strategy_intf_(NULL) {
+CompManager::CompManager() : strategy_lib_(NULL), strategy_intf_(NULL), registered_displays_(0),
+                             configured_displays_(0), safe_mode_(false) {
 }
 
 DisplayError CompManager::Init(const HWResourceInfo &hw_res_info) {
@@ -102,9 +103,12 @@
     delete comp_mgr_device;
     return error;
   }
-
+  SET_BIT(registered_displays_, type);
   comp_mgr_device->device_type = type;
   *device = comp_mgr_device;
+  // New device has been added, so move the composition mode to safe mode until unless resources
+  // for the added display is configured properly.
+  safe_mode_ = true;
 
   return kErrorNone;
 }
@@ -115,11 +119,26 @@
   CompManagerDevice *comp_mgr_device = reinterpret_cast<CompManagerDevice *>(device);
 
   res_mgr_.UnregisterDevice(comp_mgr_device->res_mgr_device);
+  CLEAR_BIT(registered_displays_, comp_mgr_device->device_type);
+  CLEAR_BIT(configured_displays_, comp_mgr_device->device_type);
   delete comp_mgr_device;
 
   return kErrorNone;
 }
 
+void CompManager::PrepareStrategyConstraints(Handle device, HWLayers *hw_layers) {
+  CompManagerDevice *comp_mgr_device = reinterpret_cast<CompManagerDevice *>(device);
+  StrategyConstraints *constraints = &comp_mgr_device->constraints;
+
+  constraints->safe_mode = safe_mode_;
+  // If validation for the best available composition strategy with driver has failed, just
+  // fallback to GPU composition.
+  if (UNLIKELY(hw_layers->info.flags)) {
+    constraints->safe_mode = true;
+    return;
+  }
+}
+
 DisplayError CompManager::Prepare(Handle device, HWLayers *hw_layers) {
   SCOPE_LOCK(locker_);
 
@@ -128,19 +147,7 @@
 
   DisplayError error = kErrorNone;
 
-  comp_mgr_device->constraints.gpu_only = false;
-
-  // If validation for the best available composition strategy with driver has failed, just
-  // fallback to GPU composition.
-  if (UNLIKELY(hw_layers->info.flags)) {
-    // Did driver reject GPU composition as well? This will never happen.
-    if (UNLIKELY(hw_layers->info.flags & kFlagGPU)) {
-      DLOGE("Unexpected error. GPU composition validation failed.");
-      return kErrorHardware;
-    }
-
-    comp_mgr_device->constraints.gpu_only = true;
-  }
+  PrepareStrategyConstraints(device, hw_layers);
 
   // Select a composition strategy, and try to allocate resources for it.
   res_mgr_.Start(res_mgr_device);
@@ -175,6 +182,10 @@
   SCOPE_LOCK(locker_);
 
   CompManagerDevice *comp_mgr_device = reinterpret_cast<CompManagerDevice *>(device);
+  SET_BIT(configured_displays_, comp_mgr_device->device_type);
+  if (configured_displays_ == registered_displays_) {
+      safe_mode_ = false;
+  }
 
   res_mgr_.PostCommit(comp_mgr_device->res_mgr_device, hw_layers);
 }
@@ -187,10 +198,8 @@
   res_mgr_.Purge(comp_mgr_device->res_mgr_device);
 }
 
-uint32_t CompManager::GetDump(uint8_t *buffer, uint32_t length) {
+void CompManager::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
-
-  return 0;
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index e6954a8..f9c9202 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -48,9 +48,10 @@
   void Purge(Handle device);
 
   // DumpImpl method
-  virtual uint32_t GetDump(uint8_t *buffer, uint32_t length);
+  virtual void AppendDump(char *buffer, uint32_t length);
 
  private:
+  void PrepareStrategyConstraints(Handle device, HWLayers *hw_layers);
   struct CompManagerDevice {
     StrategyConstraints constraints;
     Handle res_mgr_device;
@@ -62,6 +63,11 @@
   StrategyInterface *strategy_intf_;
   StrategyDefault strategy_default_;
   ResManager res_mgr_;
+  uint64_t registered_displays_;        // Stores the bit mask of registered displays
+  uint64_t configured_displays_;        // Stores the bit mask of sucessfully configured displays
+  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
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/device_base.cpp b/displayengine/libs/core/device_base.cpp
index f991903..6dc3ebd 100644
--- a/displayengine/libs/core/device_base.cpp
+++ b/displayengine/libs/core/device_base.cpp
@@ -294,10 +294,59 @@
   return kErrorNone;
 }
 
-uint32_t DeviceBase::GetDump(uint8_t *buffer, uint32_t length) {
+void DeviceBase::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
 
-  return 0;
+  AppendString(buffer, length, "\n-----------------------");
+  AppendString(buffer, length, "\ndevice type: %u", device_type_);
+  AppendString(buffer, length, "\nstate: %u, vsync on: %u", state_, INT(vsync_enable_));
+  AppendString(buffer, length, "\nnum configs: %u, active config index: %u",
+                                num_modes_, active_mode_index_);
+
+  DeviceConfigVariableInfo &info = device_attributes_[active_mode_index_];
+  AppendString(buffer, length, "\nres:%ux%u, dpi:%.2fx%.2f, fps:%.2f, vsync period: %u",
+      info.x_pixels, info.y_pixels, info.x_dpi, info.y_dpi, info.fps, info.vsync_period_ns);
+
+  uint32_t num_layers = 0;
+  uint32_t num_hw_layers = 0;
+  if (hw_layers_.info.stack) {
+    num_layers = hw_layers_.info.stack->layer_count;
+    num_hw_layers = hw_layers_.info.count;
+  }
+
+  AppendString(buffer, length, "\n\nnum actual layers: %u, num sde layers: %u",
+                                num_layers, num_hw_layers);
+
+  for (uint32_t i = 0; i < num_hw_layers; i++) {
+    Layer &layer = hw_layers_.info.stack->layers[i];
+    LayerBuffer *input_buffer = layer.input_buffer;
+    HWLayerConfig &layer_config = hw_layers_.config[i];
+    HWPipeInfo &left_pipe = hw_layers_.config[i].left_pipe;
+    HWPipeInfo &right_pipe = hw_layers_.config[i].right_pipe;
+
+    AppendString(buffer, length, "\n\nsde idx: %u, actual idx: %u", i, hw_layers_.info.index[i]);
+    AppendString(buffer, length, "\nw: %u, h: %u, fmt: %u",
+                                  input_buffer->width, input_buffer->height, input_buffer->format);
+    AppendRect(buffer, length, "\nsrc_rect:", &layer.src_rect);
+    AppendRect(buffer, length, "\ndst_rect:", &layer.dst_rect);
+
+    AppendString(buffer, length, "\n\tleft split =>");
+    AppendString(buffer, length, "\n\t  pipe id: 0x%x", left_pipe.pipe_id);
+    AppendRect(buffer, length, "\n\t  src_roi:", &left_pipe.src_roi);
+    AppendRect(buffer, length, "\n\t  dst_roi:", &left_pipe.dst_roi);
+
+    if (layer_config.is_right_pipe) {
+      AppendString(buffer, length, "\n\tright split =>");
+      AppendString(buffer, length, "\n\t  pipe id: 0x%x", right_pipe.pipe_id);
+      AppendRect(buffer, length, "\n\t  src_roi:", &right_pipe.src_roi);
+      AppendRect(buffer, length, "\n\t  dst_roi:", &right_pipe.dst_roi);
+    }
+  }
+}
+
+void DeviceBase::AppendRect(char *buffer, uint32_t length, const char *rect_name, LayerRect *rect) {
+  AppendString(buffer, length, "%s %.1f, %.1f, %.1f, %.1f",
+                                rect_name, rect->left, rect->top, rect->right, rect->bottom);
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/device_base.h b/displayengine/libs/core/device_base.h
index 458983c..a2ef93b 100644
--- a/displayengine/libs/core/device_base.h
+++ b/displayengine/libs/core/device_base.h
@@ -34,7 +34,7 @@
 
 namespace sde {
 
-class DeviceBase : public DeviceInterface, DumpImpl, HWEventHandler   {
+class DeviceBase : public DeviceInterface, HWEventHandler, DumpImpl {
  public:
   DeviceBase(DeviceType device_type, DeviceEventHandler *event_handler,
              HWBlockType hw_block_type, HWInterface *hw_intf, CompManager *comp_manager);
@@ -52,13 +52,14 @@
   virtual DisplayError SetConfig(uint32_t mode);
   virtual DisplayError SetVSyncState(bool enable);
 
-  // DumpImpl method
-  virtual uint32_t GetDump(uint8_t *buffer, uint32_t length);
-
   // Implement the HWEventHandlers
   virtual DisplayError VSync(int64_t timestamp);
   virtual DisplayError Blank(bool blank);
 
+  // DumpImpl method
+  virtual void AppendDump(char *buffer, uint32_t length);
+  void AppendRect(char *buffer, uint32_t length, const char *rect_name, LayerRect *rect);
+
  protected:
   Locker locker_;
   DeviceType device_type_;
diff --git a/displayengine/libs/core/dump_impl.cpp b/displayengine/libs/core/dump_impl.cpp
index b15573c..b000ea7 100644
--- a/displayengine/libs/core/dump_impl.cpp
+++ b/displayengine/libs/core/dump_impl.cpp
@@ -27,6 +27,9 @@
 #define SDE_MODULE_NAME "DumpInterface"
 #include <utils/debug.h>
 
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
 #include <utils/constants.h>
 
 #include "dump_impl.h"
@@ -36,12 +39,18 @@
 DumpImpl* DumpImpl::dump_list_[] = { 0 };
 uint32_t DumpImpl::dump_count_ = 0;
 
-DisplayError DumpInterface::GetDump(uint8_t *buffer, uint32_t length, uint32_t *filled) {
-  if (!buffer || !length || !filled) {
+DisplayError DumpInterface::GetDump(char *buffer, uint32_t length) {
+  if (!buffer || !length) {
     return kErrorParameters;
   }
 
-  DumpImpl::GetDump(buffer, length, filled);
+  buffer[0] = '\0';
+  DumpImpl::AppendString(buffer, length, "\n-------- Snapdragon Display Engine --------");
+  for (uint32_t i = 0; i < DumpImpl::dump_count_; i++) {
+    DumpImpl::dump_list_[i]->AppendDump(buffer, length);
+  }
+  DumpImpl::AppendString(buffer, length, "\n-------------------------------------------\n");
+
   return kErrorNone;
 }
 
@@ -53,12 +62,16 @@
   Unregister(this);
 }
 
-// Caller has to ensure that it does not create or destroy devices while using dump interface.
-void DumpImpl::GetDump(uint8_t *buffer, uint32_t length, uint32_t *filled) {
-  *filled = 0;
-  for (uint32_t i = 0; (i < DumpImpl::dump_count_) && (*filled < length); i++) {
-    *filled += DumpImpl::dump_list_[i]->GetDump(buffer + *filled, length - *filled);
+void DumpImpl::AppendString(char *buffer, uint32_t length, const char *format, ...) {
+  uint32_t filled = UINT32(strlen(buffer));
+  if (filled >= length) {
+    return;
   }
+  buffer += filled;
+
+  va_list list;
+  va_start(list, format);
+  vsnprintf(buffer, length - filled, format, list);
 }
 
 // Every object is created or destroyed through display core only, which itself protects the
diff --git a/displayengine/libs/core/dump_impl.h b/displayengine/libs/core/dump_impl.h
index 7d652ec..83197e5 100644
--- a/displayengine/libs/core/dump_impl.h
+++ b/displayengine/libs/core/dump_impl.h
@@ -33,8 +33,8 @@
  public:
   // To be implemented in the modules which will add dump information to final dump buffer.
   // buffer address & length will be already adjusted before calling into these modules.
-  virtual uint32_t GetDump(uint8_t *buffer, uint32_t length) = 0;
-  static void GetDump(uint8_t *buffer, uint32_t length, uint32_t *filled);
+  virtual void AppendDump(char *buffer, uint32_t length) = 0;
+  static void AppendString(char *buffer, uint32_t length, const char *format, ...);
 
  protected:
   DumpImpl();
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 3057fa2..8dc3330 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -25,12 +25,12 @@
 // SDE_LOG_TAG definition must precede debug.h include.
 #define SDE_LOG_TAG kTagCore
 #define SDE_MODULE_NAME "HWFrameBuffer"
+#define __STDC_FORMAT_MACROS
 #include <utils/debug.h>
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <math.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
@@ -50,18 +50,26 @@
 extern int virtual_close(int fd);
 extern int virtual_poll(struct pollfd *fds,  nfds_t num, int timeout);
 extern ssize_t virtual_pread(int fd, void *data, size_t count, off_t offset);
+extern FILE* virtual_fopen(const char *fname, const char *mode);
+extern int virtual_fclose(FILE* fileptr);
+extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
+
+
 #endif
 
 namespace sde {
 
 HWFrameBuffer::HWFrameBuffer() : event_thread_name_("SDE_EventThread"), fake_vsync_(false),
-                                 exit_threads_(false) {
+                                 exit_threads_(false), fb_path_("/sys/class/graphics/fb") {
   // Pointer to actual driver interfaces.
   ioctl_ = ::ioctl;
   open_ = ::open;
   close_ = ::close;
   poll_ = ::poll;
   pread_ = ::pread;
+  fopen_ = ::fopen;
+  fclose_ = ::fclose;
+  getline_ = ::getline;
 
 #ifdef DISPLAY_CORE_VIRTUAL_DRIVER
   // If debug property to use virtual driver is set, point to virtual driver interfaces.
@@ -71,20 +79,39 @@
     close_ = virtual_close;
     poll_ = virtual_poll;
     pread_ = virtual_pread;
+    fopen_ = virtual_fopen;
+    fclose_ = virtual_fclose;
+    getline_ = virtual_getline;
   }
 #endif
+  for (int i = 0; i < kHWBlockMax; i ++) {
+    fb_node_index_[i] = -1;
+  }
 }
 
 DisplayError HWFrameBuffer::Init() {
   DisplayError error = kErrorNone;
-
-  // TODO(user): Need to read the fbnode info, hw capabilities here
-
-  // Open nodes for polling
   char node_path[kMaxStringLength] = {0};
   char data[kMaxStringLength] = {0};
   const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event"};
 
+  // Read the fb node index
+  PopulateFBNodeIndex();
+  if (fb_node_index_[kHWPrimary] == -1) {
+    DLOGE("HW Display Device Primary should be present");
+    error = kErrorHardware;
+    goto CleanupOnError;
+  }
+
+  // Populate Primary Panel Info(Used for Partial Update)
+  PopulatePanelInfo(fb_node_index_[kHWPrimary]);
+  // Populate HW Capabilities
+  error = PopulateHWCapabilities();
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  // Open nodes for polling
   for (int display = 0; display < kNumPhysicalDisplays; display++) {
     for (int event = 0; event < kNumDisplayEvents; event++) {
       poll_fds_[display][event].fd = -1;
@@ -96,12 +123,12 @@
       for (int event = 0; event < kNumDisplayEvents; event++) {
         pollfd &poll_fd = poll_fds_[display][event];
 
-        snprintf(node_path, sizeof(node_path), "/sys/class/graphics/fb%d/%s",
-                (display == 0) ? 0 : 1/*TODO(user): HDMI fb node index*/, event_name[event]);
+        snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_node_index_[display],
+                 event_name[event]);
 
         poll_fd.fd = open_(node_path, O_RDONLY);
         if (poll_fd.fd < 0) {
-          DLOGE("open failed for display=%d event=%zu, error=%s", display, event, strerror(errno));
+          DLOGE("open failed for display=%d event=%d, error=%s", display, event, strerror(errno));
           error = kErrorHardware;
           goto CleanupOnError;
         }
@@ -150,19 +177,7 @@
 }
 
 DisplayError HWFrameBuffer::GetHWCapabilities(HWResourceInfo *hw_res_info) {
-  // Hardcode for 8084 for now.
-  hw_res_info->mdp_version = 500;
-  hw_res_info->hw_revision = 0x10030001;
-  hw_res_info->num_dma_pipe = 2;
-  hw_res_info->num_vig_pipe = 4;
-  hw_res_info->num_rgb_pipe = 4;
-  hw_res_info->num_rotator = 2;
-  hw_res_info->num_control = 5;
-  hw_res_info->num_mixer_to_disp = 4;
-  hw_res_info->max_scale_up = 20;
-  hw_res_info->max_scale_down = 4;
-  hw_res_info->has_non_scalar_rgb = true;
-  hw_res_info->is_src_split = true;
+  *hw_res_info = hw_resource_;
 
   return kErrorNone;
 }
@@ -195,7 +210,10 @@
   }
 
   *device = hw_context;
-  event_handler_[device_id] = eventhandler;
+
+  // Store EventHandlers for two Physical displays
+  if (device_id < kNumPhysicalDisplays)
+    event_handler_[device_id] = eventhandler;
 
   return error;
 }
@@ -498,7 +516,7 @@
           ssize_t length = pread_(poll_fd.fd, data, kMaxStringLength, 0);
           if (length < 0) {
             // If the read was interrupted - it is not a fatal error, just continue.
-            DLOGE("Failed to read event:%zu for display=%d : %s", event, display, strerror(errno));
+            DLOGE("Failed to read event:%d for display=%d: %s", event, display, strerror(errno));
             continue;
           }
 
@@ -528,4 +546,231 @@
   return;
 }
 
+void HWFrameBuffer::PopulateFBNodeIndex() {
+  char stringbuffer[kMaxStringLength];
+  DisplayError error = kErrorNone;
+  HWBlockType hwblock = kHWPrimary;
+  char *line = stringbuffer;
+  size_t len = kMaxStringLength;
+  ssize_t read;
+
+
+  for (int i = 0; i < kHWBlockMax; i++) {
+    snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_type", fb_path_, i);
+    FILE* fileptr = fopen_(stringbuffer, "r");
+    if (fileptr == NULL) {
+      DLOGE("File not found %s", stringbuffer);
+      continue;
+    }
+    read = getline_(&line, &len, fileptr);
+    if (read ==-1) {
+      fclose_(fileptr);
+      continue;
+    }
+    // TODO(user): For now, assume primary to be cmd/video/lvds/edp mode panel only
+    // Need more concrete info from driver
+    if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
+      pri_panel_info_.type = kCommandModePanel;
+      hwblock = kHWPrimary;
+    } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0))  {
+      pri_panel_info_.type = kVideoModePanel;
+      hwblock = kHWPrimary;
+    } else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
+      pri_panel_info_.type = kLVDSPanel;
+      hwblock = kHWPrimary;
+    } else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
+      pri_panel_info_.type = kEDPPanel;
+      hwblock = kHWPrimary;
+    } else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
+      hwblock = kHWHDMI;
+    } else if ((strncmp(line, "writeback panel", strlen("writeback panel")) == 0)) {
+      hwblock = kHWWriteback0;
+    } else {
+      DLOGE("Unknown panel type = %s index = %d", line, i);
+    }
+    fb_node_index_[hwblock] = i;
+    fclose_(fileptr);
+  }
+}
+
+void HWFrameBuffer::PopulatePanelInfo(int fb_index) {
+  char stringbuffer[kMaxStringLength];
+  FILE* fileptr = NULL;
+  snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_panel_info", fb_path_, fb_index);
+  fileptr = fopen_(stringbuffer, "r");
+  if (fileptr == NULL) {
+    DLOGE("Failed to open msm_fb_panel_info node");
+    return;
+  }
+
+  size_t len = kMaxStringLength;
+  ssize_t read;
+  char *line = stringbuffer;
+  while ((read = getline_(&line, &len, fileptr)) != -1) {
+    int token_count = 0;
+    const int max_count = 10;
+    char *tokens[max_count] = { NULL };
+    if (!ParseLine(line, tokens, max_count, &token_count)) {
+      if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
+        pri_panel_info_.partial_update = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
+        pri_panel_info_.left_align = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
+        pri_panel_info_.width_align = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
+        pri_panel_info_.top_align = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
+        pri_panel_info_.height_align = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
+        pri_panel_info_.min_roi_width = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
+        pri_panel_info_.min_roi_height = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
+        pri_panel_info_.needs_roi_merge = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "dynamic_fps_en", strlen("dyn_fps_en"))) {
+        pri_panel_info_.dynamic_fps = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
+        pri_panel_info_.min_fps = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
+        pri_panel_info_.max_fps= atoi(tokens[1]);
+      }
+    }
+  }
+  fclose_(fileptr);
+}
+
+// Get SDE HWCapabalities from the sysfs
+DisplayError HWFrameBuffer::PopulateHWCapabilities() {
+  DisplayError error = kErrorNone;
+  FILE *fileptr = NULL;
+  char stringbuffer[kMaxStringLength];
+  int token_count = 0;
+  const int max_count = 10;
+  char *tokens[max_count] = { NULL };
+  snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/mdp/caps", fb_path_,
+           fb_node_index_[kHWPrimary]);
+  fileptr = fopen_(stringbuffer, "rb");
+
+  if (fileptr == NULL) {
+    DLOGE("File '%s' not found", stringbuffer);
+    return kErrorHardware;
+  }
+
+  size_t len = kMaxStringLength;
+  ssize_t read;
+  char *line = stringbuffer;
+  hw_resource_.hw_version = kHWMdssVersion5;
+  while ((read = getline_(&line, &len, fileptr)) != -1) {
+    // parse the line and update information accordingly
+    if (!ParseLine(line, tokens, max_count, &token_count)) {
+      if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
+        hw_resource_.hw_revision = atoi(tokens[1]);  // HW Rev, v1/v2
+      } else if (!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
+        hw_resource_.num_rgb_pipe = (uint8_t)atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
+        hw_resource_.num_vig_pipe = (uint8_t)atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
+        hw_resource_.num_dma_pipe = (uint8_t)atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "cursor_pipes", strlen("cursor_pipes"))) {
+        hw_resource_.num_cursor_pipe = (uint8_t)atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "blending_stages", strlen("blending_stages"))) {
+        hw_resource_.num_blending_stages = (uint8_t)atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_downscale_ratio", strlen("max_downscale_ratio"))) {
+        hw_resource_.max_scale_down = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_upscale_ratio", strlen("max_upscale_ratio"))) {
+        hw_resource_.max_scale_up = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_bandwidth_low", strlen("max_bandwidth_low"))) {
+        hw_resource_.max_bandwidth_low = atol(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_bandwidth_high", strlen("max_bandwidth_high"))) {
+        hw_resource_.max_bandwidth_high = atol(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
+        hw_resource_.max_mixer_width = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "features", strlen("features"))) {
+        for (int i = 0; i < token_count; i++) {
+          if (!strncmp(tokens[i], "bwc", strlen("bwc"))) {
+            hw_resource_.has_bwc = true;
+          } else if (!strncmp(tokens[i], "decimation", strlen("decimation"))) {
+            hw_resource_.has_decimation = true;
+          } else if (!strncmp(tokens[i], "tile_format", strlen("tile_format"))) {
+            hw_resource_.has_macrotile = true;
+          } else if (!strncmp(tokens[i], "src_split", strlen("src_split"))) {
+            hw_resource_.is_src_split = true;
+          } else if (!strncmp(tokens[i], "non_scalar_rgb", strlen("non_scalar_rgb"))) {
+            hw_resource_.has_non_scalar_rgb = true;
+          } else if (!strncmp(tokens[i], "rotator_downscale", strlen("rotator_downscale"))) {
+            hw_resource_.has_rotator_downscale = true;
+          }
+        }
+      }
+    }
+  }
+  fclose_(fileptr);
+
+  // Split info - for MDSS Version 5 - No need to check version here
+  snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/msm_fb_split", fb_path_,
+           fb_node_index_[kHWPrimary]);
+  fileptr = fopen_(stringbuffer, "r");
+  if (fileptr) {
+    // Format "left right" space as delimiter
+    read = getline_(&line, &len, fileptr);
+    if (read != -1) {
+      if (!ParseLine(line, tokens, max_count, &token_count)) {
+        hw_resource_.split_info.left_split = atoi(tokens[0]);
+        hw_resource_.split_info.right_split = atoi(tokens[1]);
+      }
+    }
+    fclose_(fileptr);
+  }
+
+  // SourceSplit enabled - Get More information
+  if (hw_resource_.is_src_split) {
+    snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/msm_fb_src_split_info", fb_path_,
+             fb_node_index_[kHWPrimary]);
+    fileptr = fopen_(stringbuffer, "r");
+    if (fileptr) {
+      read = getline_(&line, &len, fileptr);
+      if (read != -1) {
+        if (!strncmp(line, "src_split_always", strlen("src_split_always"))) {
+          hw_resource_.always_src_split = true;
+        }
+      }
+      fclose_(fileptr);
+    }
+  }
+
+  DLOGI("SDE Version: %d SDE Revision: %x RGB : %d, VIG: %d DMA: %d Cursor: %d",
+        hw_resource_.hw_version, hw_resource_.hw_revision, hw_resource_.num_rgb_pipe,
+        hw_resource_.num_vig_pipe, hw_resource_.num_dma_pipe, hw_resource_.num_cursor_pipe);
+  DLOGI("Upscale Ratio: %d Downscale Ratio: %d Blending Stages: %d", hw_resource_.max_scale_up,
+        hw_resource_.max_scale_down, hw_resource_.num_blending_stages);
+  DLOGI("BWC: %d Decimation: %d Tile Format: %d: Rotator Downscale: %d",  hw_resource_.has_bwc,
+        hw_resource_.has_decimation, hw_resource_.has_macrotile,
+        hw_resource_.has_rotator_downscale);
+  DLOGI("Left Split: %d Right Split: %d", hw_resource_.split_info.left_split,
+        hw_resource_.split_info.right_split);
+  DLOGI("SourceSplit: %d Always: %d", hw_resource_.is_src_split, hw_resource_.always_src_split);
+  DLOGI("MaxLowBw: %"PRIu64" MaxHighBw: %"PRIu64"", hw_resource_.max_bandwidth_low,
+        hw_resource_.max_bandwidth_high);
+
+  return error;
+}
+
+int HWFrameBuffer::ParseLine(char *input, char *tokens[], int max_token, int *count) {
+  char *tmp_token = NULL;
+  char *temp_ptr;
+  int index = 0;
+  const char *delim = ", =\n";
+  if (!input) {
+    return -1;
+  }
+  tmp_token = strtok_r(input, delim, &temp_ptr);
+  while (tmp_token && index < max_token) {
+    tokens[index++] = tmp_token;
+    tmp_token = strtok_r(NULL, delim, &temp_ptr);
+  }
+  *count = index;
+
+  return 0;
+}
+
 }  // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index b64e869..6b844af 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -25,9 +25,12 @@
 #ifndef __HW_FRAMEBUFFER_H__
 #define __HW_FRAMEBUFFER_H__
 
+#include <stdio.h>
+#include <stdlib.h>
 #include <linux/msm_mdp.h>
 #include <poll.h>
 #include <pthread.h>
+
 #include "hw_interface.h"
 
 namespace sde {
@@ -57,14 +60,45 @@
     int device_fd;
   };
 
+  enum PanelType {
+    kNoPanel,
+    kCommandModePanel,
+    kVideoModePanel,
+    kDTvPanel,
+    kWriteBackPanel,
+    kLVDSPanel,
+    kEDPPanel,
+  };
+
   enum {
     kHWEventVSync,
     kHWEventBlank,
   };
 
+  // Maps to the msm_fb_panel_info
+  struct PanelInfo {
+    PanelType type;        // Smart or Dumb
+    bool partial_update;   // Partial update feature
+    int left_align;        // ROI left alignment restriction
+    int width_align;       // ROI width alignment restriction
+    int top_align;;        // ROI top alignment restriction
+    int height_align;      // ROI height alignment restriction
+    int min_roi_width;     // Min width needed for ROI
+    int min_roi_height;    // Min height needed for ROI
+    bool needs_roi_merge;  // Merge ROI's of both the DSI's
+    bool dynamic_fps;      // Panel Supports dynamic fps
+    uint32_t min_fps;      // Min fps supported by panel
+    uint32_t max_fps;      // Max fps supported by panel
+
+    PanelInfo() : type(kNoPanel), partial_update(false), left_align(false), width_align(false),
+      top_align(false), height_align(false), min_roi_width(0), min_roi_height(0),
+      needs_roi_merge(false), dynamic_fps(false), min_fps(0), max_fps(0) { }
+  };
+
   static const int kMaxStringLength = 1024;
   static const int kNumPhysicalDisplays = 2;
   static const int kNumDisplayEvents = 2;
+  static const int kHWMdssVersion5 = 500;  // MDSS_V5
 
   inline void SetFormat(uint32_t *target, const LayerBufferFormat &source);
   inline void SetBlending(uint32_t *target, const LayerBlending &source);
@@ -77,12 +111,23 @@
   void HandleVSync(int display_id, char *data);
   void HandleBlank(int display_id, char *data);
 
+  // Populates HW FrameBuffer Node Index
+  void PopulateFBNodeIndex();
+  // Populates the Panel Info based on node index
+  void PopulatePanelInfo(int fb_index);
+  // Populates HW Capabilities
+  DisplayError PopulateHWCapabilities();
+  int ParseLine(char *input, char *token[], int max_token, int *count);
+
   // Pointers to system calls which are either mapped to actual system call or virtual driver.
   int (*ioctl_)(int, int, ...);
   int (*open_)(const char *, int, ...);
   int (*close_)(int);
   int (*poll_)(struct pollfd *, nfds_t, int);
   ssize_t (*pread_)(int, void *, size_t, off_t);
+  FILE* (*fopen_)( const char *fname, const char *mode );;
+  int (*fclose_)(FILE* fileptr);
+  ssize_t (*getline_)(char **lineptr, size_t *linelen, FILE *stream);
 
   // Store the Device EventHandlers - used for callback
   HWEventHandler *event_handler_[kNumPhysicalDisplays];
@@ -91,6 +136,10 @@
   const char *event_thread_name_;
   bool fake_vsync_;
   bool exit_threads_;
+  HWResourceInfo hw_resource_;
+  int fb_node_index_[kHWBlockMax];
+  const char* fb_path_;
+  PanelInfo pri_panel_info_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index ddf631e..bb2a8a9 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -41,11 +41,13 @@
 };
 
 struct HWResourceInfo {
-  uint32_t mdp_version;
+  uint32_t hw_version;
   uint32_t hw_revision;
   uint32_t num_dma_pipe;
   uint32_t num_vig_pipe;
   uint32_t num_rgb_pipe;
+  uint32_t num_cursor_pipe;
+  uint32_t num_blending_stages;
   uint32_t num_rotator;
   uint32_t num_control;
   uint32_t num_mixer_to_disp;
@@ -54,20 +56,29 @@
   uint32_t num_smp_per_pipe;
   uint32_t max_scale_up;
   uint32_t max_scale_down;
-  uint32_t max_bandwidth_low;
-  uint32_t max_bandwidth_high;
+  uint64_t max_bandwidth_low;
+  uint64_t max_bandwidth_high;
+  uint32_t max_mixer_width;
+  struct SplitInfo {
+    uint32_t left_split;
+    uint32_t right_split;
+    SplitInfo() : left_split(0), right_split(0) { }
+  } split_info;
   bool has_bwc;
   bool has_decimation;
+  bool has_macrotile;
+  bool has_rotator_downscale;
   bool has_non_scalar_rgb;
   bool is_src_split;
-  bool has_microtile;
+  bool always_src_split;
 
   HWResourceInfo()
-    : mdp_version(0), hw_revision(0), num_dma_pipe(0), num_vig_pipe(0),
-      num_rgb_pipe(0), num_rotator(0), num_control(0), num_mixer_to_disp(0), smp_total(0),
-      smp_size(0), num_smp_per_pipe(0), max_scale_up(0), max_scale_down(0), max_bandwidth_low(0),
-      max_bandwidth_high(0), has_bwc(false), has_decimation(false), has_non_scalar_rgb(false),
-      is_src_split(false), has_microtile(false) { }
+    : hw_version(0), hw_revision(0), num_dma_pipe(0), num_vig_pipe(0), num_rgb_pipe(0),
+      num_cursor_pipe(0), num_blending_stages(0), num_rotator(0), num_control(0),
+      num_mixer_to_disp(0), smp_total(0), smp_size(0), num_smp_per_pipe(0), max_scale_up(0),
+      max_scale_down(0), max_bandwidth_low(0), max_bandwidth_high(0), max_mixer_width(2048),
+      has_bwc(false), has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
+      has_non_scalar_rgb(false), is_src_split(false), always_src_split(false) { }
 };
 
 struct HWPipeInfo {
@@ -89,7 +100,7 @@
 
 struct HWLayers {
   HWLayersInfo info;
-  HWLayerConfig config[kNumLayersMax];
+  HWLayerConfig config[kMaxSDELayers];
 };
 
 struct HWDeviceAttributes : DeviceConfigVariableInfo {
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 16060d8..de73437 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -441,10 +441,8 @@
           ((dst_roi.bottom - dst_roi.top) != (src_roi.bottom - src_roi.top));
 }
 
-uint32_t ResManager::GetDump(uint8_t *buffer, uint32_t length) {
+void ResManager::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
-
-  return 0;
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index ccd6433..b2698c9 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -48,7 +48,7 @@
   void Purge(Handle device);
 
   // DumpImpl method
-  virtual uint32_t GetDump(uint8_t *buffer, uint32_t length);
+  virtual void AppendDump(char *buffer, uint32_t length);
 
  private:
   enum PipeId {
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 51b9a80..9dfa920 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -287,8 +287,7 @@
     return;
   }
 
-  uint32_t filled = 0;
-  DumpInterface::GetDump(reinterpret_cast<uint8_t *>(buffer), length, &filled);
+  DumpInterface::GetDump(buffer, length);
 }
 
 int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
diff --git a/displayengine/libs/hwc/hwc_sink.cpp b/displayengine/libs/hwc/hwc_sink.cpp
index e5b07f5..0fb4b8c 100644
--- a/displayengine/libs/hwc/hwc_sink.cpp
+++ b/displayengine/libs/hwc/hwc_sink.cpp
@@ -226,6 +226,9 @@
     return 0;
   }
 
+  // Reset Layer stack flags
+  layer_stack_.flags = LayerStackFlags();
+
   // Configure each layer
   for (size_t i = 0; i < num_hw_layers; i++) {
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
@@ -244,6 +247,12 @@
       layer_buffer->planes[0].fd = pvt_handle->fd;
       layer_buffer->planes[0].offset = pvt_handle->offset;
       layer_buffer->planes[0].stride = pvt_handle->width;
+      if (pvt_handle->bufferType == BUFFER_TYPE_VIDEO) {
+        layer_stack_.flags.video_present = true;
+      }
+      if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+        layer_stack_.flags.secure_present = true;
+      }
     }
 
     SetRect(&layer.dst_rect, hwc_layer.displayFrame);
@@ -252,7 +261,6 @@
         SetRect(&layer.visible_regions.rect[j], hwc_layer.visibleRegionScreen.rects[j]);
     }
     SetRect(&layer.dirty_regions.rect[0], hwc_layer.dirtyRect);
-
     SetComposition(&layer.composition, hwc_layer.compositionType);
     SetBlending(&layer.blending, hwc_layer.blending);
 
@@ -264,6 +272,11 @@
 
     layer.plane_alpha = hwc_layer.planeAlpha;
     layer.flags.skip = ((hwc_layer.flags & HWC_SKIP_LAYER) > 0);
+    layer.flags.updating = (layer_stack_cache_.layer_cache[i].handle != hwc_layer.handle);
+
+    if (layer.flags.skip) {
+      layer_stack_.flags.skip_present = true;
+    }
   }
 
   // Configure layer stack
@@ -275,15 +288,61 @@
     return -EINVAL;
   }
 
+  bool needs_fb_refresh = NeedsFrameBufferRefresh(content_list);
+
   for (size_t i = 0; i < num_hw_layers; i++) {
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
     Layer &layer = layer_stack_.layers[i];
-    SetComposition(&hwc_layer.compositionType, layer.composition);
+    // if current frame does not need frame buffer redraw, then mark them for HWC_OVERLAY
+    LayerComposition composition = needs_fb_refresh ? layer.composition : kCompositionSDE;
+    SetComposition(&hwc_layer.compositionType, composition);
   }
+  // Cache the current layer stack information like layer_count, composition type and layer handle
+  // for the future.
+  CacheLayerStackInfo(content_list);
 
   return 0;
 }
 
+void HWCSink::CacheLayerStackInfo(hwc_display_contents_1_t *content_list) {
+  uint32_t layer_count = layer_stack_.layer_count;
+
+  for (size_t i = 0; i < layer_count; i++) {
+    Layer &layer = layer_stack_.layers[i];
+    layer_stack_cache_.layer_cache[i].handle = content_list->hwLayers[i].handle;
+    layer_stack_cache_.layer_cache[i].composition = layer.composition;
+  }
+  layer_stack_cache_.layer_count = layer_count;
+}
+
+bool HWCSink::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
+  uint32_t layer_count = layer_stack_.layer_count;
+
+  // Frame buffer needs to be refreshed for the following reasons:
+  // 1. Any layer is marked skip in the current layer stack.
+  // 2. Any layer is added/removed/layer properties changes in the current layer stack.
+  // 3. Any layer handle is changed and it is marked for GPU composition
+  // 4. Any layer's current composition is different from previous composition.
+  if ((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
+       layer_stack_.flags.geometry_changed) {
+    return true;
+  }
+
+  for (size_t i = 0; i < layer_count; i++) {
+    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+    Layer &layer = layer_stack_.layers[i];
+    LayerCache &layer_cache = layer_stack_cache_.layer_cache[i];
+    if (layer_cache.composition != layer.composition) {
+      return true;
+    }
+    if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 int HWCSink::CommitLayerStack(hwc_display_contents_1_t *content_list) {
   size_t num_hw_layers = content_list->numHwLayers;
   if (UNLIKELY(num_hw_layers <= 1)) {
diff --git a/displayengine/libs/hwc/hwc_sink.h b/displayengine/libs/hwc/hwc_sink.h
index 340aabd..551a77b 100644
--- a/displayengine/libs/hwc/hwc_sink.h
+++ b/displayengine/libs/hwc/hwc_sink.h
@@ -43,6 +43,18 @@
   int SetState(DeviceState state);
 
  protected:
+  // Maximum number of layers supported by display engine.
+  static const uint32_t kMaxLayerCount = 32;
+
+  // Structure to track memory allocation for layer stack (layers, rectangles) object.
+  struct LayerStackMemory : LayerStack {
+    static const size_t kSizeSteps = 4096;  // Default memory allocation.
+    uint8_t *raw;  // Pointer to byte array.
+    size_t size;  // Current number of allocated bytes.
+
+    LayerStackMemory() : raw(NULL), size(0) { }
+  };
+
   HWCSink(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DeviceType type, int id);
   virtual ~HWCSink() { }
 
@@ -60,18 +72,32 @@
   inline void SetBlending(LayerBlending *target, const int32_t &source);
   inline int SetFormat(LayerBufferFormat *target, const int &source);
 
-  // Structure to track memory allocation for layer stack (layers, rectangles) object.
-  struct LayerStackMemory : LayerStack {
-    static const size_t kSizeSteps = 4096;  // Default memory allocation.
-    uint8_t *raw;  // Pointer to byte array.
-    size_t size;  // Current number of allocated bytes.
-  } layer_stack_;
-
+  LayerStackMemory layer_stack_;
   CoreInterface *core_intf_;
   hwc_procs_t const **hwc_procs_;
   DeviceType type_;
   int id_;
   DeviceInterface *device_intf_;
+
+ private:
+  struct LayerCache {
+    buffer_handle_t handle;
+    LayerComposition composition;
+
+    LayerCache() : handle(NULL), composition(kCompositionGPU) { }
+  };
+
+  struct LayerStackCache {
+    LayerCache layer_cache[kMaxLayerCount];
+    uint32_t layer_count;
+
+    LayerStackCache() : layer_count(0) { }
+  };
+
+  bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
+  void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
+
+  LayerStackCache layer_stack_cache_;
 };
 
 }  // namespace sde
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 3e16072..58cf374 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -523,9 +523,15 @@
             qdutils::MDPVersion::getInstance().isSrcSplitAlways();
     const uint32_t lSplit = getLeftSplit(ctx, mDpy);
     const uint32_t cropWidth = sourceCrop.right - sourceCrop.left;
+    const uint32_t cropHeight = sourceCrop.bottom - sourceCrop.top;
+    const uint32_t dstWidth = displayFrame.right - displayFrame.left;
+    const uint32_t dstHeight = displayFrame.bottom - displayFrame.top;
+    const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
+    const uint32_t mixerClock = lSplit;
 
     if((cropWidth > qdutils::MDPVersion::getInstance().getMaxMixerWidth()) or
-            (primarySplitAlways and cropWidth > lSplit)) {
+            (primarySplitAlways and
+            (cropWidth > lSplit or layerClock > mixerClock))) {
         destR = ov.getPipe(pipeSpecs);
         if(destR == ovutils::OV_INVALID) {
             ALOGE("%s: No pipes available to configure fb for dpy %d's right"
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index a2a5f2d..aa7783c 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -532,7 +532,8 @@
             }
 
             /* deduct any opaque region from visibleRect */
-            if (layer->blending == HWC_BLENDING_NONE)
+            if (layer->blending == HWC_BLENDING_NONE &&
+                    layer->planeAlpha == 0xFF)
                 visibleRect = deductRect(visibleRect, res);
         }
     }
@@ -638,7 +639,8 @@
                 return false;
             }
 
-            if (layer->blending == HWC_BLENDING_NONE) {
+            if (layer->blending == HWC_BLENDING_NONE &&
+                    layer->planeAlpha == 0xFF) {
                 visibleRectL = deductRect(visibleRectL, l_res);
                 visibleRectR = deductRect(visibleRectR, r_res);
             }
@@ -2568,18 +2570,26 @@
     MDPVersion& mdpHw = MDPVersion::getInstance();
     bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
             mdpHw.isSrcSplitAlways();
-    int lSplit = getLeftSplit(ctx, mDpy);
-    int dstWidth = dst.right - dst.left;
-    int cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
+    const uint32_t lSplit = getLeftSplit(ctx, mDpy);
+    const uint32_t dstWidth = dst.right - dst.left;
+    const uint32_t dstHeight = dst.bottom - dst.top;
+    const uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
             crop.right - crop.left;
+    const uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
+            crop.bottom - crop.top;
+    //Approximation to actual clock, ignoring the common factors in pipe and
+    //mixer cases like line_time
+    const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
+    const uint32_t mixerClock = lSplit;
 
     //TODO Even if a 4k video is going to be rot-downscaled to dimensions under
     //pipe line length, we are still using 2 pipes. This is fine just because
     //this is source split where destination doesn't matter. Evaluate later to
     //see if going through all the calcs to save a pipe is worth it
-    if(dstWidth > (int) mdpHw.getMaxMixerWidth() or
-            cropWidth > (int) mdpHw.getMaxMixerWidth() or
-            (primarySplitAlways and (cropWidth > lSplit))) {
+    if(dstWidth > mdpHw.getMaxMixerWidth() or
+            cropWidth > mdpHw.getMaxMixerWidth() or
+            (primarySplitAlways and
+            (cropWidth > lSplit or layerClock > mixerClock))) {
         pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
         if(pipe_info.rIndex == ovutils::OV_INVALID) {
             return false;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 51e23de..916fbc7 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1383,7 +1383,8 @@
         //see if there is no blending required.
         //If it is opaque see if we can substract this region from below
         //layers.
-        if(list->hwLayers[i].blending == HWC_BLENDING_NONE) {
+        if(list->hwLayers[i].blending == HWC_BLENDING_NONE &&
+                list->hwLayers[i].planeAlpha == 0xFF) {
             int j= i-1;
             hwc_rect_t& topframe =
                 (hwc_rect_t&)list->hwLayers[i].displayFrame;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 2da8512..741527c 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -674,6 +674,11 @@
     return ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected;
 }
 
+inline uint32_t getLayerClock(const uint32_t& dstW, const uint32_t& dstH,
+        const uint32_t& srcH) {
+    return max(dstW, (srcH * dstW) / dstH);
+}
+
 };
 
 #endif //HWC_UTILS_H