Merge "gralloc: Fix a missed unmap."
diff --git a/common.mk b/common.mk
index 464f296..183ee99 100644
--- a/common.mk
+++ b/common.mk
@@ -29,6 +29,10 @@
     common_flags += -DVENUS_COLOR_FORMAT
 endif
 
+ifeq ($(call is-board-platform-in-list, $(MASTER_SIDE_CP_TARGET_LIST)), true)
+    common_flags += -DMASTER_SIDE_CP
+endif
+
 common_deps  :=
 kernel_includes :=
 
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
index e4a73c3..2493c13 100644
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -54,6 +54,9 @@
   kFormatRGB888,        //!< 8-bits Red, Green, Blue interleaved in RGB order. No Alpha.
   kFormatBGR888,        //!< 8-bits Blue, Green, Red interleaved in BGR order. No Alpha.
   kFormatRGB565,        //!< 5-bit Red, 6-bit Green, 5-bit Blue interleaved in RGB order. No Alpha.
+  kFormatRGBA8888Ubwc,  //!< UBWC aligned RGBA8888 format
+  kFormatRGBX8888Ubwc,  //!< UBWC aligned RGBX8888 format
+  kFormatRGB565Ubwc,    //!< UBWC aligned RGB565 format
 
   /* All YUV-Planar formats, Any new format will be added towards end of this group to maintain
      backward compatibility.
@@ -99,6 +102,8 @@
                                       //!< horizontally subsampled interleaved VU-plane:
                                       //!<    v(0), u(1), v(2), u(3) ... v(n-1), u(n)
 
+  kFormatYCbCr420SPVenusUbwc,         //!< UBWC aligned YCbCr420SemiPlanarVenus format
+
   /* All YUV-Packed formats, Any new format will be added towards end of this group to maintain
      backward compatibility.
   */
@@ -107,15 +112,6 @@
                                       //!<    y(0), u(0), y(1), v(0), y(2), u(2), y(3), v(2)
                                       //!<    y(n-1), u(n-1), y(n), v(n-1)
 
-  /* All UBWC aligned formats. Any new format will be added towards end of this group to maintain
-     backward compatibility.
-  */
-  kFormatRGBA8888Ubwc = 0x400,        //!< UBWC aligned RGBA8888 format
-
-  kFormatRGB565Ubwc,                  //!< UBWC aligned RGB565 format
-
-  kFormatYCbCr420SPVenusUbwc,         //!< UBWC aligned Venus NV12 format
-
   kFormatInvalid = 0xFFFFFFFF,
 };
 
@@ -138,14 +134,30 @@
   @sa LayerBuffer
 */
 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
-  uint64_t macro_tile : 1;  //!< This flag shall be set by client to indicate that the buffer format
-                            //!< is macro tiled.
+  union {
+    struct {
+      uint32_t secure : 1;          //!< This flag shall be set by client to indicate that the
+                                    //!< buffer need to be handled securely.
 
-  LayerBufferFlags() : secure(0), video(0), macro_tile(0) { }
+      uint32_t video  : 1;          //!< This flag shall be set by client to indicate that the
+                                    //!< buffer is video/ui buffer.
+
+      uint32_t macro_tile : 1;      //!< This flag shall be set by client to indicate that the
+                                    //!< buffer format is macro tiled.
+
+      uint32_t interlace : 1;       //!< This flag shall be set by the client to indicate that
+                                    //!< the buffer has interlaced content.
+
+      uint32_t secure_display : 1;
+                                    //!< This flag shall be set by the client to indicate that the
+                                    //!< secure display session is in progress. Secure display
+                                    //!< session can not coexist with non-secure session.
+      };
+
+      uint32_t flags;   //!< For initialization purpose only. Client shall not refer it directly.
+  };
+
+  LayerBufferFlags() : flags(0) { }
 };
 
 /*! @brief This structure defines a layer buffer handle which contains raw buffer and its associated
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
index d85fd98..66f60e7 100644
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -92,15 +92,22 @@
   @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. Display Device will not consider it for composition.
+  union {
+    struct {
+      uint32_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.
+      uint32_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) { }
+    uint32_t flags;   //!< For initialization purpose only. Client shall not refer it directly.
+  };
+
+  LayerFlags() : flags(0) { }
 };
 
 /*! @brief This structure defines flags associated with a layer stack. The 1-bit flag can be set to
@@ -109,24 +116,29 @@
   @sa LayerBuffer
 */
 struct LayerStackFlags {
-  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.
+  union {
+    struct {
+      uint32_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.
+      uint32_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.
+      uint32_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.
+      uint32_t secure_present : 1;    //!< This flag will be set to true, if the current layer
+                                      //!< stack contains secure layers.
 
-  uint64_t animating : 1;         //!< This flag shall be set by client to indicate that the current
-                                  //!< frame is animating.
+      uint32_t animating : 1;         //!< This flag shall be set by client to indicate that the
+                                      //!<  current frame is animating.
+      };
 
-  LayerStackFlags()
-    : geometry_changed(0), skip_present(0), video_present(0), secure_present(0), animating(0) { }
+      uint32_t flags;   //!< For initialization purpose only. Client shall not refer it directly.
+  };
+
+  LayerStackFlags() : flags(0) { }
 };
 
 /*! @brief This structure defines a rectanglular area inside a display layer.
diff --git a/displayengine/include/private/hw_info_types.h b/displayengine/include/private/hw_info_types.h
index 49abafe..1740615 100644
--- a/displayengine/include/private/hw_info_types.h
+++ b/displayengine/include/private/hw_info_types.h
@@ -65,6 +65,7 @@
   uint64_t max_bandwidth_low;
   uint64_t max_bandwidth_high;
   uint32_t max_mixer_width;
+  uint32_t max_pipe_width;
   uint32_t max_pipe_bw;
   uint32_t max_sde_clk;
   float clk_fudge_factor;
@@ -81,8 +82,8 @@
       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(1),
       max_scale_down(1), max_bandwidth_low(0), max_bandwidth_high(0), max_mixer_width(2048),
-      max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false), has_ubwc(false),
-      has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
+      max_pipe_width(2048), max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
+      has_ubwc(false), has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
       has_non_scalar_rgb(false), is_src_split(false) { }
 
   void Reset() { *this = HWResourceInfo(); }
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 8725a7b..47beac0 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -22,6 +22,7 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#include <stdio.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
 
@@ -146,6 +147,11 @@
           continue;
         }
         error = rotator_ctrl_->Prepare(display_rotator_ctx_, &hw_layers_);
+      } else {
+        // Release all the previous rotator sessions.
+        if (rotator_ctrl_) {
+          error = rotator_ctrl_->Purge(display_rotator_ctx_, &hw_layers_);
+        }
       }
 
       if (error == kErrorNone) {
@@ -409,9 +415,11 @@
                          num_modes_, active_mode_index_);
 
   DisplayConfigVariableInfo &info = display_attributes_[active_mode_index_];
-  DumpImpl::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);
+  DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%.2f,"
+                         "vsync period: %u", info.x_pixels, info.y_pixels, info.x_dpi,
+                         info.y_dpi, info.fps, info.vsync_period_ns);
+
+  DumpImpl::AppendString(buffer, length, "\n");
 
   uint32_t num_layers = 0;
   uint32_t num_hw_layers = 0;
@@ -420,64 +428,101 @@
     num_hw_layers = hw_layers_.info.count;
   }
 
-  DumpImpl::AppendString(buffer, length, "\n\nnum actual layers: %u, num sde layers: %u",
-                         num_layers, num_hw_layers);
+  if (num_hw_layers == 0) {
+    DumpImpl::AppendString(buffer, length, "\nNo hardware layers programmed");
+    return;
+  }
+
+  HWLayersInfo &layer_info = hw_layers_.info;
+  LayerRect &l_roi = layer_info.left_partial_update;
+  LayerRect &r_roi = layer_info.right_partial_update;
+  DumpImpl::AppendString(buffer, length, "\nROI(L T R B) : LEFT(%d %d %d %d), RIGHT(%d %d %d %d)",
+                         INT(l_roi.left), INT(l_roi.top), INT(l_roi.right), INT(l_roi.bottom),
+                         INT(r_roi.left), INT(r_roi.top), INT(r_roi.right), INT(r_roi.bottom));
+
+  const char *header  = "\n| Idx |  Comp Type  |  Split | WB |  Pipe |    W x H    |       Format       |  Src Rect (L T R B) |  Dst Rect (L T R B) |  Z |    Flags   | Deci(HxV) |";  //NOLINT
+  const char *newline = "\n|-----|-------------|--------|----|-------|-------------|--------------------|---------------------|---------------------|----|------------|-----------|";  //NOLINT
+  const char *format  = "\n| %3s | %11s "     "| %6s " "| %2s | 0x%03x | %4d x %4d | %18s "            "| %4d %4d %4d %4d "  "| %4d %4d %4d %4d "  "| %2s | %10s "   "| %9s |";  //NOLINT
+
+  DumpImpl::AppendString(buffer, length, "\n");
+  DumpImpl::AppendString(buffer, length, newline);
+  DumpImpl::AppendString(buffer, length, header);
+  DumpImpl::AppendString(buffer, length, newline);
 
   for (uint32_t i = 0; i < num_hw_layers; i++) {
-    Layer &layer = hw_layers_.info.stack->layers[hw_layers_.info.index[i]];
+    uint32_t layer_index = hw_layers_.info.index[i];
+    Layer &layer = hw_layers_.info.stack->layers[layer_index];
     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;
-
     HWRotatorSession &hw_rotator_session = layer_config.hw_rotator_session;
-    HWRotateInfo &left_rotate = hw_rotator_session.hw_rotate_info[0];
-    HWRotateInfo &right_rotate = hw_rotator_session.hw_rotate_info[1];
 
-    DumpImpl::AppendString(buffer, length, "\n\nsde idx: %u, actual idx: %u", i,
-                           hw_layers_.info.index[i]);
-    DumpImpl::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);
+    char idx[8] = { 0 };
+    const char *comp_type = GetName(layer.composition);
+    const char *buffer_format = GetName(input_buffer->format);
+    const char *rotate_split[2] = { "Rot-L", "Rot-R" };
+    const char *comp_split[2] = { "Comp-L", "Comp-R" };
 
-    if (left_rotate.valid) {
-      DumpImpl::AppendString(buffer, length, "\n\tleft rotate =>");
-      DumpImpl::AppendString(buffer, length, "\n\t  pipe id: 0x%x", left_rotate.pipe_id);
-      AppendRect(buffer, length, "\n\t  src_roi:", &left_rotate.src_roi);
-      AppendRect(buffer, length, "\n\t  dst_roi:", &left_rotate.dst_roi);
+    snprintf(idx, sizeof(idx), "%d", layer_index);
+
+    for (uint32_t count = 0; count < hw_rotator_session.hw_block_count; count++) {
+      char writeback_id[8];
+      HWRotateInfo &rotate = hw_rotator_session.hw_rotate_info[count];
+      LayerRect &src_roi = rotate.src_roi;
+      LayerRect &dst_roi = rotate.dst_roi;
+
+      snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id);
+
+      DumpImpl::AppendString(buffer, length, format, idx, comp_type, rotate_split[count],
+                             writeback_id, rotate.pipe_id, input_buffer->width,
+                             input_buffer->height, buffer_format, INT(src_roi.left),
+                             INT(src_roi.top), INT(src_roi.right), INT(src_roi.bottom),
+                             INT(dst_roi.left), INT(dst_roi.top), INT(dst_roi.right),
+                             INT(dst_roi.bottom), "-", "-    ", "-    ");
+
+      // print the below only once per layer block, fill with spaces for rest.
+      idx[0] = 0;
+      comp_type = "";
     }
 
-    if (right_rotate.valid) {
-      DumpImpl::AppendString(buffer, length, "\n\tright rotate =>");
-      DumpImpl::AppendString(buffer, length, "\n\t  pipe id: 0x%x", right_rotate.pipe_id);
-      AppendRect(buffer, length, "\n\t  src_roi:", &right_rotate.src_roi);
-      AppendRect(buffer, length, "\n\t  dst_roi:", &right_rotate.dst_roi);
+    if (hw_rotator_session.hw_block_count > 0) {
+      input_buffer = &hw_rotator_session.output_buffer;
+      buffer_format = GetName(input_buffer->format);
     }
 
-    if (left_pipe.valid) {
-      DumpImpl::AppendString(buffer, length, "\n\tleft pipe =>");
-      DumpImpl::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);
+    for (uint32_t count = 0; count < 2; count++) {
+      char decimation[16];
+      char flags[16];
+      char z_order[8];
+      HWPipeInfo &pipe = (count == 0) ? layer_config.left_pipe : layer_config.right_pipe;
+
+      if (!pipe.valid) {
+        continue;
+      }
+
+      LayerRect &src_roi = pipe.src_roi;
+      LayerRect &dst_roi = pipe.dst_roi;
+
+      snprintf(z_order, sizeof(z_order), "%d", pipe.z_order);
+      snprintf(flags, sizeof(flags), "0x%08x", layer.flags.flags);
+      snprintf(decimation, sizeof(decimation), "%3d x %3d", pipe.horizontal_decimation,
+               pipe.vertical_decimation);
+
+      DumpImpl::AppendString(buffer, length, format, idx, comp_type, comp_split[count],
+                             "-", pipe.pipe_id, input_buffer->width, input_buffer->height,
+                             buffer_format, INT(src_roi.left), INT(src_roi.top),
+                             INT(src_roi.right), INT(src_roi.bottom), INT(dst_roi.left),
+                             INT(dst_roi.top), INT(dst_roi.right), INT(dst_roi.bottom),
+                             z_order, flags, decimation);
+
+      // print the below only once per layer block, fill with spaces for rest.
+      idx[0] = 0;
+      comp_type = "";
     }
 
-    if (right_pipe.valid) {
-      DumpImpl::AppendString(buffer, length, "\n\tright pipe =>");
-      DumpImpl::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);
-    }
+    DumpImpl::AppendString(buffer, length, newline);
   }
 }
 
-void DisplayBase::AppendRect(char *buffer, uint32_t length, const char *rect_name,
-                             LayerRect *rect) {
-  DumpImpl::AppendString(buffer, length, "%s %.1f, %.1f, %.1f, %.1f",
-                         rect_name, rect->left, rect->top, rect->right, rect->bottom);
-}
-
 int DisplayBase::GetBestConfig() {
   return (num_modes_ == 1) ? 0 : -1;
 }
@@ -497,5 +542,44 @@
   return false;
 }
 
-}  // namespace sde
+const char * DisplayBase::GetName(const LayerComposition &composition) {
+  switch (composition) {
+  case kCompositionGPU:         return "GPU";
+  case kCompositionSDE:         return "SDE";
+  case kCompositionGPUTarget:   return "GPU_TARGET";
+  default:                      return "UNKNOWN";
+  }
+}
 
+const char * DisplayBase::GetName(const LayerBufferFormat &format) {
+  switch (format) {
+  case kFormatARGB8888:                 return "ARGB_8888";
+  case kFormatRGBA8888:                 return "RGBA_8888";
+  case kFormatBGRA8888:                 return "BGRA_8888";
+  case kFormatXRGB8888:                 return "XRGB_8888";
+  case kFormatRGBX8888:                 return "RGBX_8888";
+  case kFormatBGRX8888:                 return "BGRX_8888";
+  case kFormatRGBA5551:                 return "RGBA_5551";
+  case kFormatRGBA4444:                 return "RGBA_4444";
+  case kFormatRGB888:                   return "RGB_888";
+  case kFormatBGR888:                   return "BGR_888";
+  case kFormatRGB565:                   return "RGB_565";
+  case kFormatRGBA8888Ubwc:             return "RGBA_8888_UBWC";
+  case kFormatRGBX8888Ubwc:             return "RGBX_8888_UBWC";
+  case kFormatRGB565Ubwc:               return "RGB_565_UBWC";
+  case kFormatYCbCr420Planar:           return "Y_CB_CR_420";
+  case kFormatYCrCb420Planar:           return "Y_CR_CB_420";
+  case kFormatYCbCr420SemiPlanar:       return "Y_CBCR_420";
+  case kFormatYCrCb420SemiPlanar:       return "Y_CRCB_420";
+  case kFormatYCbCr420SemiPlanarVenus:  return "Y_CBCR_420_VENUS";
+  case kFormatYCbCr422H1V2SemiPlanar:   return "Y_CBCR_422_H1V2";
+  case kFormatYCrCb422H1V2SemiPlanar:   return "Y_CRCB_422_H1V2";
+  case kFormatYCbCr422H2V1SemiPlanar:   return "Y_CBCR_422_H2V1";
+  case kFormatYCrCb422H2V1SemiPlanar:   return "Y_CRCB_422_H2V2";
+  case kFormatYCbCr420SPVenusUbwc:      return "Y_CBCR_420_VENUS_UBWC";
+  case kFormatYCbCr422H2V1Packed:       return "YCBYCR_422_H2V1";
+  default:                              return "UNKNOWN";
+  }
+}
+
+}  // namespace sde
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 1edef9e..0a33011 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -60,15 +60,14 @@
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
 
- private:
-  bool IsRotationRequired(HWLayers *hw_layers);
-
  protected:
   // DumpImpl method
   void AppendDump(char *buffer, uint32_t length);
-  void AppendRect(char *buffer, uint32_t length, const char *rect_name, LayerRect *rect);
 
   virtual int GetBestConfig();
+  bool IsRotationRequired(HWLayers *hw_layers);
+  const char * GetName(const LayerComposition &composition);
+  const char * GetName(const LayerBufferFormat &format);
 
   DisplayType display_type_;
   DisplayEventHandler *event_handler_;
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 1a96884..ea1b80c 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -26,6 +26,7 @@
 #define __DISPLAY_HDMI_H__
 
 #include "display_base.h"
+#include "dump_impl.h"
 
 namespace sde {
 
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index d6116fa..0fa5d2b 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -186,7 +186,7 @@
     return kErrorNotSupported;
   }
 
-  switch(mode) {
+  switch (mode) {
   case kModeVideo:
     hw_display_mode = kModeVideo;
     break;
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index be422de..1ed28b2 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -26,6 +26,7 @@
 #define __DISPLAY_PRIMARY_H__
 
 #include "display_base.h"
+#include "dump_impl.h"
 
 namespace sde {
 
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index 8e7a764..f868612 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -26,6 +26,7 @@
 #define __DISPLAY_VIRTUAL_H__
 
 #include "display_base.h"
+#include "dump_impl.h"
 
 namespace sde {
 
diff --git a/displayengine/libs/core/dump_impl.cpp b/displayengine/libs/core/dump_impl.cpp
index a5aca81..f9219f3 100755
--- a/displayengine/libs/core/dump_impl.cpp
+++ b/displayengine/libs/core/dump_impl.cpp
@@ -44,7 +44,7 @@
   for (uint32_t i = 0; i < DumpImpl::dump_count_; i++) {
     DumpImpl::dump_list_[i]->AppendDump(buffer, length);
   }
-  DumpImpl::AppendString(buffer, length, "\n-------------------------------------------\n");
+  DumpImpl::AppendString(buffer, length, "\n\n");
 
   return kErrorNone;
 }
diff --git a/displayengine/libs/core/fb/hw_device.cpp b/displayengine/libs/core/fb/hw_device.cpp
index 230092a..6db1370 100644
--- a/displayengine/libs/core/fb/hw_device.cpp
+++ b/displayengine/libs/core/fb/hw_device.cpp
@@ -214,6 +214,7 @@
     HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
     HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
     HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+    bool is_rotator_used = (hw_rotator_session->hw_block_count != 0);
     mdp_input_layer mdp_layer;
 
     for (uint32_t count = 0; count < 2; count++) {
@@ -246,18 +247,7 @@
 
         SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
         SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
-
-        // Flips will be taken care by rotator, if layer requires 90 rotation. So Dont use MDP for
-        // flip operation, if layer transform is 90.
-        if (!layer.transform.rotation) {
-          if (layer.transform.flip_vertical) {
-            mdp_layer.flags |= MDP_LAYER_FLIP_UD;
-          }
-
-          if (layer.transform.flip_horizontal) {
-            mdp_layer.flags |= MDP_LAYER_FLIP_LR;
-          }
-        }
+        SetMDPFlags(layer, is_rotator_used, &mdp_layer.flags);
 
         mdp_scale_data* mdp_scale = GetScaleDataRef(mdp_layer_count);
 #ifdef USES_SCALAR
@@ -328,9 +318,9 @@
   return kErrorNone;
 }
 
-void HWDevice::DumpLayerCommit(mdp_layer_commit &layer_commit) {
-  mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
-  mdp_input_layer *mdp_layers = mdp_commit.input_layers;
+void HWDevice::DumpLayerCommit(const mdp_layer_commit &layer_commit) {
+  const mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
+  const mdp_input_layer *mdp_layers = mdp_commit.input_layers;
 
   DLOGE("mdp_commit: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
   DLOGE("left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x, mdp_commit.left_roi.y,
@@ -340,10 +330,10 @@
   for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
     DLOGE("mdp_commit: layer_cnt = %d, pipe_ndx = %x, zorder = %d, flags = %x",
           i, mdp_layers[i].pipe_ndx, mdp_layers[i].z_order, mdp_layers[i].flags);
-    mdp_rect &src_rect = mdp_layers[i].src_rect;
+    const mdp_rect &src_rect = mdp_layers[i].src_rect;
     DLOGE("src rect: x = %d, y = %d, w = %d, h = %d",
           src_rect.x, src_rect.y, src_rect.w, src_rect.h);
-    mdp_rect &dst_rect = mdp_layers[i].dst_rect;
+    const mdp_rect &dst_rect = mdp_layers[i].dst_rect;
     DLOGE("dst rect: x = %d, y = %d, w = %d, h = %d",
           dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
   }
@@ -523,6 +513,7 @@
   case kFormatYCbCr422H2V1Packed:       *target = MDP_YCBYCR_H2V1;       break;
   case kFormatYCbCr420SemiPlanarVenus:  *target = MDP_Y_CBCR_H2V2_VENUS; break;
   case kFormatRGBA8888Ubwc:             *target = MDP_RGBA_8888_UBWC;    break;
+  case kFormatRGBX8888Ubwc:             *target = MDP_RGBX_8888_UBWC;    break;
   case kFormatRGB565Ubwc:               *target = MDP_RGB_565_UBWC;      break;
   case kFormatYCbCr420SPVenusUbwc:      *target = MDP_Y_CBCR_H2V2_UBWC;  break;
   default:
@@ -548,6 +539,8 @@
   case kFormatBGRA8888:
   case kFormatRGBX8888:
   case kFormatBGRX8888:
+  case kFormatRGBA8888Ubwc:
+  case kFormatRGBX8888Ubwc:
     *target = width * 4;
     break;
   case kFormatRGB888:
@@ -555,7 +548,8 @@
     *target = width * 3;
     break;
   case kFormatRGB565:
-    *target = width * 3;
+  case kFormatRGB565Ubwc:
+    *target = width * 2;
     break;
   case kFormatYCbCr420SemiPlanarVenus:
   case kFormatYCbCr420SPVenusUbwc:
@@ -597,6 +591,35 @@
   target->h = UINT32(source.bottom) - target->y;
 }
 
+void HWDevice::SetMDPFlags(const Layer &layer, const bool &is_rotator_used,
+                           uint32_t *mdp_flags) {
+  LayerBuffer *input_buffer = layer.input_buffer;
+
+  // Flips will be taken care by rotator, if layer uses rotator for downscale/rotation. So ignore
+  // flip flags for MDP.
+  if (!is_rotator_used) {
+    if (layer.transform.flip_vertical) {
+      *mdp_flags |= MDP_LAYER_FLIP_UD;
+    }
+
+    if (layer.transform.flip_horizontal) {
+      *mdp_flags |= MDP_LAYER_FLIP_LR;
+    }
+  }
+
+  if (input_buffer->flags.interlace) {
+    *mdp_flags |= MDP_LAYER_DEINTERLACE;
+  }
+
+  if (input_buffer->flags.secure) {
+    *mdp_flags |= MDP_LAYER_SECURE_SESSION;
+  }
+
+  if (input_buffer->flags.secure_display) {
+    *mdp_flags |= MDP_SECURE_DISPLAY_OVERLAY_SESSION;
+  }
+}
+
 void HWDevice::SyncMerge(const int &fd1, const int &fd2, int *target) {
   if (fd1 >= 0 && fd2 >= 0) {
     buffer_sync_handler_->SyncMerge(fd1, fd2, target);
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
index 8dca6f9..734b69d 100644
--- a/displayengine/libs/core/fb/hw_device.h
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -72,12 +72,13 @@
   static const int kNumPhysicalDisplays = 2;
   static const int kNumDisplayEvents = 4;
 
-  void DumpLayerCommit(mdp_layer_commit &layer_commit);
+  void DumpLayerCommit(const mdp_layer_commit &layer_commit);
   DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
   DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
                          uint32_t width, uint32_t *target);
   void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
   void SetRect(const LayerRect &source, mdp_rect *target);
+  void SetMDPFlags(const Layer &layer, const bool &is_rotator_used, uint32_t *mdp_flags);
   void SyncMerge(const int &fd1, const int &fd2, int *target);
 
   // Retrieves HW FrameBuffer Node Index
diff --git a/displayengine/libs/core/fb/hw_info.cpp b/displayengine/libs/core/fb/hw_info.cpp
index cddb590..7833c3c 100644
--- a/displayengine/libs/core/fb/hw_info.cpp
+++ b/displayengine/libs/core/fb/hw_info.cpp
@@ -123,6 +123,8 @@
         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], "max_pipe_width", strlen("max_pipe_width"))) {
+        hw_resource->max_pipe_width = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
         hw_resource->max_pipe_bw = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
diff --git a/displayengine/libs/core/fb/hw_rotator.cpp b/displayengine/libs/core/fb/hw_rotator.cpp
index cc9bd1a..c698445 100644
--- a/displayengine/libs/core/fb/hw_rotator.cpp
+++ b/displayengine/libs/core/fb/hw_rotator.cpp
@@ -173,17 +173,7 @@
       if (hw_rotate_info->valid) {
         mdp_rotation_item *mdp_rot_item = &mdp_rot_request_.list[rot_count];
 
-        if (rot90) {
-          mdp_rot_item->flags |= MDP_ROTATION_90;
-        }
-
-        if (layer.transform.flip_horizontal) {
-          mdp_rot_item->flags |= MDP_ROTATION_FLIP_LR;
-        }
-
-        if (layer.transform.flip_vertical) {
-          mdp_rot_item->flags |= MDP_ROTATION_FLIP_UD;
-        }
+        SetMDPFlags(layer, &mdp_rot_item->flags);
 
         SetRect(hw_rotate_info->src_roi, &mdp_rot_item->src_rect);
         SetRect(hw_rotate_info->dst_roi, &mdp_rot_item->dst_rect);
@@ -274,6 +264,27 @@
   }
 }
 
+ void HWRotator::SetMDPFlags(const Layer &layer, uint32_t *mdp_flags) {
+  LayerTransform transform = layer.transform;
+  bool rot90 = (transform.rotation == 90.0f);
+
+  if (rot90) {
+    *mdp_flags |= MDP_ROTATION_90;
+  }
+
+  if (transform.flip_horizontal) {
+    *mdp_flags |= MDP_ROTATION_FLIP_LR;
+  }
+
+  if (transform.flip_vertical) {
+    *mdp_flags |= MDP_ROTATION_FLIP_UD;
+  }
+
+  if (layer.input_buffer->flags.secure) {
+    *mdp_flags |= MDP_ROTATION_SECURE;
+  }
+}
+
 DisplayError HWRotator::Validate(HWLayers *hw_layers) {
   SetCtrlParams(hw_layers);
 
diff --git a/displayengine/libs/core/fb/hw_rotator.h b/displayengine/libs/core/fb/hw_rotator.h
index 3b4eebe..b78b657 100644
--- a/displayengine/libs/core/fb/hw_rotator.h
+++ b/displayengine/libs/core/fb/hw_rotator.h
@@ -53,6 +53,7 @@
   void ResetParams();
   void SetCtrlParams(HWLayers *hw_layers);
   void SetBufferParams(HWLayers *hw_layers);
+  void SetMDPFlags(const Layer &layer, uint32_t *rot_flags);
 
   struct mdp_rotation_request mdp_rot_request_;
   struct mdp_rotation_item mdp_rot_layers_[kMaxSDELayers * 2];  // split panel (left + right)
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 3cea3db..c5a8a06 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -122,7 +122,7 @@
   // For perf/power optimization, even if "always_src_split" is enabled, use 2 pipes only if:
   // 1. Source width is greater than split_left (left_mixer_width)
   // 2. Pipe clock exceeds the mixer clock
-  if ((src_width > kMaxSourcePipeWidth) || (dst_width > kMaxSourcePipeWidth) ||
+  if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_width) ||
       (display_resource_ctx->display_attributes.always_src_split &&
       ((src_width > left_mixer_width) || (pipe_clock > mixer_clock)))) {
     SplitRect(transform.flip_horizontal, src_rect, dst_rect, &left_pipe->src_roi,
@@ -169,7 +169,7 @@
     crop_right_valid = CalculateCropRects(scissor, transform, &crop_right, &dst_right);
   }
 
-  if (crop_left_valid && (crop_left.right - crop_left.left) > kMaxSourcePipeWidth) {
+  if (crop_left_valid && (crop_left.right - crop_left.left) > hw_res_info_.max_pipe_width) {
     if (crop_right_valid) {
       DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
                crop_left.right - crop_left.left, crop_right.right - crop_right.left);
@@ -181,7 +181,8 @@
     left_pipe->valid = true;
     right_pipe->valid = true;
     crop_right_valid = true;
-  } else if (crop_right_valid && (crop_right.right - crop_right.left) > kMaxSourcePipeWidth) {
+  } else if (crop_right_valid &&
+             (crop_right.right - crop_right.left) > hw_res_info_.max_pipe_width) {
     if (crop_left_valid) {
       DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
                crop_left.right - crop_left.left, crop_right.right - crop_right.left);
@@ -234,12 +235,11 @@
 
   for (uint32_t i = 0; i < layer_info.count; i++) {
     Layer& layer = layer_info.stack->layers[layer_info.index[i]];
-    float rot_scale = 1.0f;
-    if (!IsValidDimension(layer.src_rect, layer.dst_rect)) {
-      DLOGV_IF(kTagResources, "Input is invalid");
-      Log(kTagResources, "input layer src_rect", layer.src_rect);
-      Log(kTagResources, "input layer dst_rect", layer.dst_rect);
-      return kErrorNotSupported;
+    float rotator_scale_factor = 1.0f;
+
+    error = ValidateLayerDimensions(layer);
+    if (error != kErrorNone) {
+      return error;
     }
 
     LayerRect scissor, src_rect, dst_rect;
@@ -253,7 +253,7 @@
     HWPipeInfo &right_pipe = layer_config->right_pipe;
     HWRotatorSession *hw_rotator_session = &layer_config->hw_rotator_session;
     LayerTransform transform = layer.transform;
-    bool rot90 = IsRotationNeeded(transform.rotation);
+    bool rotated90 = IsRotationNeeded(transform.rotation);
 
     if (!CalculateCropRects(scissor, layer.transform, &src_rect, &dst_rect)) {
       layer_config->Reset();
@@ -268,8 +268,19 @@
       Normalize(align_x, align_y, &src_rect);
     }
 
-    if (ValidateScaling(layer, src_rect, dst_rect, &rot_scale)) {
-      return kErrorNotSupported;
+    error = ValidateDimensions(src_rect, dst_rect, rotated90);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    error = ValidateScaling(src_rect, dst_rect, rotated90);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    error = GetRotatorScaleFactor(src_rect, dst_rect, rotated90, &rotator_scale_factor);
+    if (error != kErrorNone) {
+      return error;
     }
 
     // config rotator first
@@ -278,8 +289,8 @@
     }
     hw_rotator_session->hw_block_count = 0;
 
-    if (rot90 || UINT32(rot_scale) != 1) {
-      RotationConfig(layer, rot_scale, &src_rect, layer_config, rotate_count);
+    if (rotated90 || UINT32(rotator_scale_factor) != 1) {
+      RotationConfig(layer, rotator_scale_factor, &src_rect, layer_config, rotate_count);
       // rotator will take care of flipping, reset tranform
       transform = LayerTransform();
     }
@@ -306,7 +317,7 @@
     Log(kTagResources, "input layer src_rect", layer.src_rect);
     Log(kTagResources, "input layer dst_rect", layer.dst_rect);
     for (uint32_t k = 0; k < hw_rotator_session->hw_block_count; k++) {
-      DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f", k, rot_scale);
+      DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f", k, rotator_scale_factor);
       Log(kTagResources, "rotate src", hw_rotator_session->hw_rotate_info[k].src_roi);
       Log(kTagResources, "rotate dst", hw_rotator_session->hw_rotate_info[k].dst_roi);
     }
@@ -343,91 +354,6 @@
   return error;
 }
 
-DisplayError ResManager::ValidateScaling(const Layer &layer, const LayerRect &crop,
-                                         const LayerRect &dst, float *rot_scale) {
-  bool rotated90 = IsRotationNeeded(layer.transform.rotation) && (rot_scale != NULL);
-  float crop_width = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
-  float crop_height = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
-  float dst_width = dst.right - dst.left;
-  float dst_height = dst.bottom - dst.top;
-
-  if ((dst_width < 1.0f) || (dst_height < 1.0f)) {
-    DLOGV_IF(kTagResources, "dst ROI is too small w = %.0f, h = %.0f, right = %.0f, bottom = %.0f",
-             dst_width, dst_height, dst.right, dst.bottom);
-    return kErrorNotSupported;
-  }
-
-  if ((crop_width < 1.0f) || (crop_height < 1.0f)) {
-    DLOGV_IF(kTagResources, "src ROI is too small w = %.0f, h = %.0f, right = %.0f, bottom = %.0f",
-             crop_width, crop_height, crop.right, crop.bottom);
-    return kErrorNotSupported;
-  }
-
-  if ((UINT32(crop_width - dst_width) == 1) || (UINT32(crop_height - dst_height) == 1)) {
-    DLOGV_IF(kTagResources, "One pixel downscaling detected crop_w = %.0f, dst_w = %.0f, " \
-             "crop_h = %.0f, dst_h = %.0f", crop_width, dst_width, crop_height, dst_height);
-    return kErrorNotSupported;
-  }
-
-  float scale_x = crop_width / dst_width;
-  float scale_y = crop_height / dst_height;
-  uint32_t rot_scale_local = 1;
-
-  if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
-    float max_scale_down = FLOAT(hw_res_info_.max_scale_down);
-
-    if (hw_res_info_.has_rotator_downscale && !property_setting_.disable_rotator_downscaling &&
-        rot_scale && !IsMacroTileFormat(layer.input_buffer)) {
-      float scale_min = MIN(scale_x, scale_y);
-      float scale_max = MAX(scale_x, scale_y);
-      // use rotator to downscale when over the pipe scaling ability
-      if (UINT32(scale_min) >= 2 && scale_max > max_scale_down) {
-        // downscaling ratio needs be the same for both direction, use the smaller one.
-        rot_scale_local = 1 << UINT32(ceilf(log2f(scale_min / max_scale_down)));
-        if (rot_scale_local > kMaxRotateDownScaleRatio)
-          rot_scale_local = kMaxRotateDownScaleRatio;
-        scale_x /= FLOAT(rot_scale_local);
-        scale_y /= FLOAT(rot_scale_local);
-      }
-      *rot_scale = FLOAT(rot_scale_local);
-    }
-
-    if (hw_res_info_.has_decimation && !property_setting_.disable_decimation &&
-               !IsMacroTileFormat(layer.input_buffer)) {
-      max_scale_down *= FLOAT(kMaxDecimationDownScaleRatio);
-    }
-
-    if (scale_x > max_scale_down || scale_y > max_scale_down) {
-      DLOGV_IF(kTagResources,
-               "Scaling down is over the limit: is_tile = %d, scale_x = %.0f, scale_y = %.0f, " \
-               "crop_w = %.0f, dst_w = %.0f, has_deci = %d, disable_deci = %d, rot_scale = %d",
-               IsMacroTileFormat(layer.input_buffer), scale_x, scale_y, crop_width, dst_width,
-               hw_res_info_.has_decimation, property_setting_.disable_decimation, rot_scale_local);
-      return kErrorNotSupported;
-    }
-  }
-
-  float max_scale_up = FLOAT(hw_res_info_.max_scale_up);
-  if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
-    if ((1.0f / scale_x) > max_scale_up) {
-      DLOGV_IF(kTagResources, "Scaling up is over limit scale_x = %f", 1.0f / scale_x);
-      return kErrorNotSupported;
-    }
-  }
-
-  if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
-    if ((1.0f / scale_y) > max_scale_up) {
-      DLOGV_IF(kTagResources, "Scaling up is over limit scale_y = %f", 1.0f / scale_y);
-      return kErrorNotSupported;
-    }
-  }
-
-  DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f, rot_scale = %d",
-           scale_x, scale_y, rot_scale_local);
-
-  return kErrorNone;
-}
-
 void ResManager::CalculateCut(const LayerTransform &transform, float *left_cut_ratio,
                               float *top_cut_ratio, float *right_cut_ratio,
                               float *bottom_cut_ratio) {
@@ -514,22 +440,239 @@
     return false;
 }
 
-bool ResManager::IsValidDimension(const LayerRect &src, const LayerRect &dst) {
-  // Make sure source in integral
-  if (src.left - roundf(src.left)     ||
-      src.top - roundf(src.top)       ||
-      src.right - roundf(src.right)   ||
-      src.bottom - roundf(src.bottom)) {
-    DLOGV_IF(kTagResources, "Input ROI is not integral");
-    return false;
+DisplayError ResManager::ValidateLayerDimensions(const Layer &layer) {
+  const LayerRect &src = layer.src_rect;
+  const LayerRect &dst = layer.dst_rect;
+  LayerBuffer *input_buffer = layer.input_buffer;
+
+  if (!IsValid(src) || !IsValid(dst)) {
+    Log(kTagResources, "input layer src_rect", src);
+    Log(kTagResources, "input layer dst_rect", dst);
+    return kErrorNotSupported;
   }
 
-  if (src.left > src.right || src.top > src.bottom || dst.left > dst.right ||
-      dst.top > dst.bottom) {
-    return false;
-  } else {
-    return true;
+  // Make sure source in integral only if it is a non secure layer.
+  if (!input_buffer->flags.secure && (src.left - roundf(src.left) || src.top - roundf(src.top) ||
+      src.right - roundf(src.right) || src.bottom - roundf(src.bottom))) {
+    DLOGV_IF(kTagResources, "Input ROI is not integral");
+    return kErrorNotSupported;
   }
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::ValidateDimensions(const LayerRect &crop, const LayerRect &dst,
+                                            bool rotated90) {
+  float crop_width = 0.0f, crop_height = 0.0f, dst_width = 0.0f, dst_height = 0.0f;
+
+  DisplayError error = GetCropAndDestination(crop, dst, rotated90, &crop_width, &crop_height,
+                                             &dst_width, &dst_height);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  if ((dst_width < 1.0f) || (dst_height < 1.0f)) {
+    DLOGV_IF(kTagResources, "dst ROI is too small w = %.0f, h = %.0f, right = %.0f, bottom = %.0f",
+             dst_width, dst_height, dst.right, dst.bottom);
+    return kErrorNotSupported;
+  }
+
+  if ((crop_width < 1.0f) || (crop_height < 1.0f)) {
+    DLOGV_IF(kTagResources, "src ROI is too small w = %.0f, h = %.0f, right = %.0f, bottom = %.0f",
+             crop_width, crop_height, crop.right, crop.bottom);
+    return kErrorNotSupported;
+  }
+
+  if ((UINT32(crop_width - dst_width) == 1) || (UINT32(crop_height - dst_height) == 1)) {
+    DLOGV_IF(kTagResources, "One pixel downscaling detected crop_w = %.0f, dst_w = %.0f, " \
+             "crop_h = %.0f, dst_h = %.0f", crop_width, dst_width, crop_height, dst_height);
+    return kErrorNotSupported;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::ValidatePipeParams(HWPipeInfo *pipe_info) {
+  DisplayError error = kErrorNone;
+
+  const LayerRect &src_rect = pipe_info->src_roi;
+  const LayerRect &dst_rect = pipe_info->dst_roi;
+
+  error = ValidateDimensions(src_rect, dst_rect, false /* rotated90 */);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = ValidateScaling(src_rect, dst_rect, false /* rotated90 */);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+                                         bool rotated90) {
+  DisplayError error = kErrorNone;
+
+  float scale_x = 1.0f;
+  float scale_y = 1.0f;
+
+  error = GetScaleFactor(crop, dst, rotated90, &scale_x, &scale_y);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = ValidateDownScaling(scale_x, scale_y);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = ValidateUpScaling(scale_x, scale_y);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::ValidateDownScaling(float scale_x, float scale_y) {
+  if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
+    float max_scale_down = FLOAT(hw_res_info_.max_scale_down);
+    float rotator_scale_factor = 1.0f;
+
+    if (hw_res_info_.has_rotator_downscale && !property_setting_.disable_rotator_downscaling) {
+      rotator_scale_factor =  GetRotatorScaleFactor(scale_x, scale_y);
+      scale_x /= rotator_scale_factor;
+      scale_y /= rotator_scale_factor;
+
+      DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f, rotator_scale_factor = %d",
+               scale_x, scale_y, rotator_scale_factor);
+    }
+
+    if (hw_res_info_.has_decimation && !property_setting_.disable_decimation) {
+      max_scale_down *= FLOAT(kMaxDecimationDownScaleRatio);
+    }
+
+    if (scale_x > max_scale_down || scale_y > max_scale_down) {
+      DLOGV_IF(kTagResources,
+               "Scaling down is over the limit: scale_x = %.0f, scale_y = %.0f, " \
+               "has_deci = %d, disable_deci = %d, rotator_scale_factor= %.0f",
+               scale_x, scale_y, hw_res_info_.has_decimation, property_setting_.disable_decimation,
+               rotator_scale_factor);
+      return kErrorNotSupported;
+    }
+  }
+
+  DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f", scale_x, scale_y);
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::ValidateUpScaling(float scale_x, float scale_y) {
+  float max_scale_up = FLOAT(hw_res_info_.max_scale_up);
+
+  if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
+    if ((1.0f / scale_x) > max_scale_up) {
+      DLOGV_IF(kTagResources, "Scaling up is over limit scale_x = %f", 1.0f / scale_x);
+      return kErrorNotSupported;
+    }
+  }
+
+  if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
+    if ((1.0f / scale_y) > max_scale_up) {
+      DLOGV_IF(kTagResources, "Scaling up is over limit scale_y = %f", 1.0f / scale_y);
+      return kErrorNotSupported;
+    }
+  }
+
+  DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f", scale_x, scale_y);
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::GetCropAndDestination(const LayerRect &crop, const LayerRect &dst,
+                                               const bool rotated90, float *crop_width,
+                                               float *crop_height, float *dst_width,
+                                               float *dst_height) {
+  if (!IsValid(crop)) {
+    Log(kTagResources, "Invalid crop rect", crop);
+    return kErrorNotSupported;
+  }
+
+  if (!IsValid(dst)) {
+    Log(kTagResources, "Invalid dst rect", dst);
+    return kErrorNotSupported;
+  }
+
+  *crop_width = crop.right - crop.left;
+  *crop_height = crop.bottom - crop.top;
+  if (rotated90) {
+    Swap(*crop_width, *crop_height);
+  }
+
+  *dst_width = dst.right - dst.left;
+  *dst_height = dst.bottom - dst.top;
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::GetRotatorScaleFactor(const LayerRect &crop, const LayerRect &dst,
+                                               bool rotated90, float *rotator_scale_factor) {
+  DisplayError error = kErrorNone;
+
+  float scale_x = 1.0f;
+  float scale_y = 1.0f;
+
+  if (hw_res_info_.has_rotator_downscale && !property_setting_.disable_rotator_downscaling) {
+    error = GetScaleFactor(crop, dst, rotated90, &scale_x, &scale_y);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    *rotator_scale_factor =  GetRotatorScaleFactor(scale_x, scale_y);
+  } else {
+    *rotator_scale_factor = 1.0f;
+  }
+
+  return kErrorNone;
+}
+
+float ResManager::GetRotatorScaleFactor(float scale_x, float scale_y) {
+  float max_scale_down = FLOAT(hw_res_info_.max_scale_down);
+  float scale_min = MIN(scale_x, scale_y);
+  float scale_max = MAX(scale_x, scale_y);
+  uint32_t rotator_scale_factor = 1;
+
+  // use rotator to downscale when over the pipe scaling ability
+  if (UINT32(scale_min) >= 2 && scale_max > max_scale_down) {
+    // downscaling ratio needs be the same for both direction, use the smaller one.
+    rotator_scale_factor = 1 << UINT32(ceilf(log2f(scale_min / max_scale_down)));
+    if (rotator_scale_factor > kMaxRotateDownScaleRatio) {
+      rotator_scale_factor = kMaxRotateDownScaleRatio;
+    }
+  }
+
+  DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f, rotator_scale_factor = %d",
+           scale_x, scale_y, rotator_scale_factor);
+
+  return FLOAT(rotator_scale_factor);
+}
+
+DisplayError ResManager::GetScaleFactor(const LayerRect &crop, const LayerRect &dst,
+                                        bool rotated90, float *scale_x, float *scale_y) {
+  float crop_width = 1.0f, crop_height = 1.0f, dst_width = 1.0f, dst_height = 1.0f;
+
+  DisplayError error = GetCropAndDestination(crop, dst, rotated90, &crop_width, &crop_height,
+                                             &dst_width, &dst_height);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  *scale_x = crop_width / dst_width;
+  *scale_y = crop_height / dst_height;
+
+  return kErrorNone;
 }
 
 DisplayError ResManager::SetDecimationFactor(HWPipeInfo *pipe) {
@@ -628,13 +771,14 @@
     }
     right_pipe->dst_roi.left = left_pipe->dst_roi.right;
   }
-  error = ValidateScaling(layer, left_pipe->src_roi, left_pipe->dst_roi, NULL);
+
+  error = ValidatePipeParams(left_pipe);
   if (error != kErrorNone) {
     goto PipeConfigExit;
   }
 
   if (right_pipe->valid) {
-    error = ValidateScaling(layer, right_pipe->src_roi, right_pipe->dst_roi, NULL);
+    error = ValidatePipeParams(right_pipe);
   }
 PipeConfigExit:
   if (error != kErrorNone) {
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 08b055b..261155f 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -40,20 +40,18 @@
 }
 
 DisplayError ResManager::Init(const HWResourceInfo &hw_res_info) {
-  hw_res_info_ = hw_res_info;
-
-  if (!hw_res_info_.max_mixer_width)
-    hw_res_info_.max_mixer_width = kMaxSourcePipeWidth;
-
   DisplayError error = kErrorNone;
+  uint32_t num_pipe = 0;
 
-  num_pipe_ = hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe + hw_res_info_.num_dma_pipe;
+  num_pipe = hw_res_info.num_vig_pipe + hw_res_info.num_rgb_pipe + hw_res_info.num_dma_pipe;
 
-  if (num_pipe_ > kPipeIdMax) {
-    DLOGE("Number of pipe is over the limit! %d", num_pipe_);
+  if (num_pipe > kPipeIdMax) {
+    DLOGE("Number of pipe is over the limit! %d", num_pipe);
     return kErrorParameters;
   }
 
+  num_pipe_ = num_pipe;
+  hw_res_info_ = hw_res_info;
   // Init pipe info
   vig_pipes_ = &src_pipes_[0];
   rgb_pipes_ = &src_pipes_[hw_res_info_.num_vig_pipe];
@@ -1043,9 +1041,17 @@
     break;
   }
 
-  // TODO(user): UBWC RGB formats will be handled separately
   if (downscale) {
     switch (input_format) {
+    case kFormatRGBA8888Ubwc:
+      *output_format = is_opaque ? kFormatRGB888 : kFormatRGBA8888;
+      break;
+    case kFormatRGBX8888Ubwc:
+      *output_format = kFormatRGB888;
+      break;
+    case kFormatRGB565Ubwc:
+      *output_format = kFormatRGB565;
+      break;
     case kFormatYCbCr420SPVenusUbwc:
       *output_format = kFormatYCbCr420SemiPlanar;
       break;
@@ -1055,6 +1061,15 @@
   } else {
     if (hw_res_info_.has_ubwc) {
       switch (input_format) {
+      case kFormatRGBA8888:
+        *output_format = kFormatRGBA8888Ubwc;
+        break;
+      case kFormatRGBX8888:
+        *output_format = kFormatRGBX8888Ubwc;
+        break;
+      case kFormatRGB565:
+        *output_format = kFormatRGB565Ubwc;
+        break;
       case kFormatYCrCb420SemiPlanar:
       case kFormatYCbCr420SemiPlanar:
       case kFormatYCbCr420SemiPlanarVenus:
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index a127645..7fa5260 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -49,6 +49,7 @@
   DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
   DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
+  DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
@@ -85,7 +86,6 @@
 
   // todo: retrieve all these from kernel
   enum {
-    kMaxSourcePipeWidth = 2048,
     kMaxInterfaceWidth = 2048,
     kMaxRotateDownScaleRatio = 8,
     kMaxDecimationDownScaleRatio = 8,
@@ -164,8 +164,6 @@
                                   const LayerTransform &transform, const LayerRect &src_rect,
                                   const LayerRect &dst_rect, HWLayerConfig *layer_config,
                                   uint32_t align_x);
-  DisplayError ValidateScaling(const Layer &layer, const LayerRect &crop,
-                               const LayerRect &dst, float *rot_scale);
   DisplayError SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
                               const LayerTransform &transform, const LayerRect &src_rect,
                               const LayerRect &dst_rect, HWLayerConfig *layer_config,
@@ -174,7 +172,19 @@
                     float *right_cut_ratio, float *bottom_cut_ratio);
   bool CalculateCropRects(const LayerRect &scissor, const LayerTransform &transform,
                           LayerRect *crop, LayerRect *dst);
-  bool IsValidDimension(const LayerRect &src, const LayerRect &dst);
+  DisplayError ValidateLayerDimensions(const Layer &layer);
+  DisplayError ValidateDimensions(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  DisplayError ValidatePipeParams(HWPipeInfo *pipe_info);
+  DisplayError ValidateDownScaling(float scale_x, float scale_y);
+  DisplayError ValidateUpScaling(float scale_x, float scale_y);
+  DisplayError GetCropAndDestination(const LayerRect &crop, const LayerRect &dst,
+                                     bool rotate90, float *crop_width, float *crop_height,
+                                     float *dst_width, float *dst_height);
+  DisplayError GetRotatorScaleFactor(const LayerRect &crop, const LayerRect &dst,
+                                     bool rotate90, float *rotator_scale_factor);
+  float GetRotatorScaleFactor(float scale_x, float scale_y);
+  DisplayError GetScaleFactor(const LayerRect &crop, const LayerRect &dst, bool rotate90,
+                              float *scale_x, float *scale_y);
   bool CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers);
   float GetPipeBw(DisplayResourceContext *display_ctx, HWPipeInfo *pipe, float bpp);
   float GetClockForPipe(DisplayResourceContext *display_ctx, HWPipeInfo *pipe);
@@ -200,7 +210,7 @@
                                HWPipeInfo *left_pipe, HWPipeInfo *right_pipe,
                                uint32_t align_x, uint32_t align_y);
   void ResourceStateLog(void);
-  DisplayError CalculateDecimation(float downscale, uint8_t* decimation);
+  DisplayError CalculateDecimation(float downscale, uint8_t *decimation);
 
   Locker locker_;
   HWResourceInfo hw_res_info_;
diff --git a/displayengine/libs/core/rotator_ctrl.cpp b/displayengine/libs/core/rotator_ctrl.cpp
index 701006c..8018e31 100644
--- a/displayengine/libs/core/rotator_ctrl.cpp
+++ b/displayengine/libs/core/rotator_ctrl.cpp
@@ -84,7 +84,7 @@
 }
 
 DisplayError RotatorCtrl::RegisterDisplay(DisplayType type, Handle *display_ctx) {
-  DisplaRotatorContext *disp_rotator_ctx = new DisplaRotatorContext();
+  DisplayRotatorContext *disp_rotator_ctx = new DisplayRotatorContext();
   if (disp_rotator_ctx == NULL) {
     return kErrorMemory;
   }
@@ -96,7 +96,7 @@
 }
 
 void RotatorCtrl::UnregisterDisplay(Handle display_ctx) {
-  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+  DisplayRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplayRotatorContext *>(display_ctx);
 
   delete disp_rotator_ctx;
   disp_rotator_ctx = NULL;
@@ -106,9 +106,9 @@
 DisplayError RotatorCtrl::Prepare(Handle display_ctx, HWLayers *hw_layers) {
   DisplayError error = kErrorNone;
 
-  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+  DisplayRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplayRotatorContext *>(display_ctx);
 
-  error = PrepareSessions(hw_layers);
+  error = PrepareSessions(disp_rotator_ctx, hw_layers);
   if (error != kErrorNone) {
     DLOGE("Prepare rotator session failed for display %d", disp_rotator_ctx->display_type);
     return error;
@@ -126,9 +126,9 @@
 DisplayError RotatorCtrl::Commit(Handle display_ctx, HWLayers *hw_layers) {
   DisplayError error = kErrorNone;
 
-  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+  DisplayRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplayRotatorContext *>(display_ctx);
 
-  error = GetOutputBuffers(hw_layers);
+  error = GetOutputBuffers(disp_rotator_ctx, hw_layers);
   if (error != kErrorNone) {
     return error;
   }
@@ -145,7 +145,8 @@
 DisplayError RotatorCtrl::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
   DisplayError error = kErrorNone;
-  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+  DisplayRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplayRotatorContext *>(display_ctx);
+  int client_id = INT(disp_rotator_ctx->display_type);
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
@@ -155,7 +156,7 @@
       continue;
     }
 
-    error = session_manager_->SetReleaseFd(hw_rotator_session);
+    error = session_manager_->SetReleaseFd(client_id, hw_rotator_session);
     if (error != kErrorNone) {
       DLOGE("Rotator Post commit failed for display %d", disp_rotator_ctx->display_type);
       return error;
@@ -165,11 +166,22 @@
   return kErrorNone;
 }
 
-DisplayError RotatorCtrl::PrepareSessions(HWLayers *hw_layers) {
+DisplayError RotatorCtrl::Purge(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplayRotatorContext *>(display_ctx);
+  int client_id = INT(disp_rotator_ctx->display_type);
+
+  session_manager_->Start(client_id);
+
+  return session_manager_->Stop(client_id);
+}
+
+DisplayError RotatorCtrl::PrepareSessions(DisplayRotatorContext *disp_rotator_ctx,
+                                          HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
   DisplayError error = kErrorNone;
+  int client_id = INT(disp_rotator_ctx->display_type);
 
-  session_manager_->Start();
+  session_manager_->Start(client_id);
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
@@ -197,20 +209,25 @@
     hw_session_config.secure = layer.input_buffer->flags.secure;
     hw_session_config.frame_rate = layer.frame_rate;
 
-    error = session_manager_->OpenSession(hw_rotator_session);
+    error = session_manager_->OpenSession(client_id, hw_rotator_session);
     if (error != kErrorNone) {
       return error;
     }
   }
 
-  session_manager_->Stop();
+  error = session_manager_->Stop(client_id);
+  if (error != kErrorNone) {
+    return error;
+  }
 
   return kErrorNone;
 }
 
-DisplayError RotatorCtrl::GetOutputBuffers(HWLayers *hw_layers) {
+DisplayError RotatorCtrl::GetOutputBuffers(DisplayRotatorContext *disp_rotator_ctx,
+                                           HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
   DisplayError error = kErrorNone;
+  int client_id = INT(disp_rotator_ctx->display_type);
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
@@ -220,7 +237,7 @@
       continue;
     }
 
-    error = session_manager_->GetNextBuffer(hw_rotator_session);
+    error = session_manager_->GetNextBuffer(client_id, hw_rotator_session);
     if (error != kErrorNone) {
       return error;
     }
diff --git a/displayengine/libs/core/rotator_ctrl.h b/displayengine/libs/core/rotator_ctrl.h
index 083f4ca..3e5deaf 100644
--- a/displayengine/libs/core/rotator_ctrl.h
+++ b/displayengine/libs/core/rotator_ctrl.h
@@ -47,6 +47,7 @@
   DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Commit(Handle display_ctx, HWLayers *hw_layers);
   DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError Purge(Handle display_ctx, HWLayers *hw_layers);
 
  private:
   enum {
@@ -55,14 +56,14 @@
     kTripleBuffering = 3,
   };
 
-  struct DisplaRotatorContext {
+  struct DisplayRotatorContext {
     DisplayType display_type;
 
-    DisplaRotatorContext() : display_type(kPrimary) { }
+    DisplayRotatorContext() : display_type(kPrimary) { }
   };
 
-  DisplayError PrepareSessions(HWLayers *hw_layers);
-  DisplayError GetOutputBuffers(HWLayers *hw_layers);
+  DisplayError PrepareSessions(DisplayRotatorContext *disp_rotator_ctx, HWLayers *hw_layers);
+  DisplayError GetOutputBuffers(DisplayRotatorContext *disp_rotator_ctx, HWLayers *hw_layers);
 
   HWRotatorInterface *hw_rotator_intf_;
   SessionManager *session_manager_;
diff --git a/displayengine/libs/core/scalar_helper.cpp b/displayengine/libs/core/scalar_helper.cpp
index c81e343..b5d8989 100644
--- a/displayengine/libs/core/scalar_helper.cpp
+++ b/displayengine/libs/core/scalar_helper.cpp
@@ -91,6 +91,7 @@
   case kFormatYCbCr422H2V1Packed:       format = scalar::YCBYCR_H2V1;       break;
   case kFormatYCbCr420SemiPlanarVenus:  format = scalar::Y_CBCR_H2V2_VENUS; break;
   case kFormatRGBA8888Ubwc:             format = scalar::RGBA_8888_UBWC;    break;
+  case kFormatRGBX8888Ubwc:             format = scalar::RGBX_8888_UBWC;    break;
   case kFormatRGB565Ubwc:               format = scalar::RGB_565_UBWC;      break;
   case kFormatYCbCr420SPVenusUbwc:      format = scalar::Y_CBCR_H2V2_UBWC;  break;
   default:
diff --git a/displayengine/libs/core/session_manager.cpp b/displayengine/libs/core/session_manager.cpp
index f87bf10..dd4c29a 100644
--- a/displayengine/libs/core/session_manager.cpp
+++ b/displayengine/libs/core/session_manager.cpp
@@ -59,23 +59,28 @@
     buffer_sync_handler_(buffer_sync_handler), active_session_count_(0) {
 }
 
-void SessionManager::Start() {
+void SessionManager::Start(const int &client_id) {
+  SCOPE_LOCK(locker_);
+
   uint32_t session_count = 0;
-  uint32_t ready_session_count = 0;
+  uint32_t acquired_session_count = 0;
 
   // Change the state of acquired session to kSessionReady
-  while ((ready_session_count < active_session_count_) && (session_count < kMaxSessionCount)) {
-    if (session_list_[session_count].state == kSessionReleased) {
-      session_count++;
-      continue;
+  while ((acquired_session_count < active_session_count_) && (session_count < kMaxSessionCount)) {
+    if (session_list_[session_count].state == kSessionAcquired) {
+      if (session_list_[session_count].client_id == client_id) {
+        session_list_[session_count].state = kSessionReady;
+      }
+      acquired_session_count++;
     }
-
-    session_list_[session_count++].state = kSessionReady;
-    ready_session_count++;
+    session_count++;
   }
 }
 
-DisplayError SessionManager::OpenSession(HWRotatorSession *hw_rotator_session) {
+DisplayError SessionManager::OpenSession(const int &client_id,
+                                         HWRotatorSession *hw_rotator_session) {
+  SCOPE_LOCK(locker_);
+
   DisplayError error = kErrorNone;
 
   const HWSessionConfig &input_config = hw_rotator_session->hw_session_config;
@@ -90,12 +95,12 @@
 
   uint32_t free_session = active_session_count_;
   uint32_t acquired_session = kMaxSessionCount;
-  uint32_t ready_session_count = 0;
+  uint32_t active_session_count = 0;
 
   // First look for a session in ready state, if no session found in ready state matching
   // with current input session config, assign a session in released state.
   for (uint32_t session_count = 0; session_count < kMaxSessionCount &&
-       ready_session_count < active_session_count_; session_count++) {
+       active_session_count < active_session_count_; session_count++) {
     HWSessionConfig &hw_session_config =
            session_list_[session_count].hw_rotator_session.hw_session_config;
 
@@ -104,17 +109,15 @@
       continue;
     }
 
-    if (session_list_[session_count].state != kSessionReady) {
-      continue;
+    if (session_list_[session_count].state == kSessionReady) {
+      if (session_list_[session_count].client_id == client_id &&
+          input_config == hw_session_config) {
+        session_list_[session_count].state = kSessionAcquired;
+        acquired_session = session_count;
+        break;
+      }
     }
-
-    if (input_config == hw_session_config) {
-      session_list_[session_count].state = kSessionAcquired;
-      acquired_session = session_count;
-      break;
-    }
-
-    ready_session_count++;
+    active_session_count++;
   }
 
   // If the input config does not match with existing config, then add new session and change the
@@ -131,31 +134,31 @@
 
     acquired_session = free_session;
     hw_rotator_session->session_id = acquired_session;
+    session_list_[acquired_session].client_id = client_id;
     active_session_count_++;
 
     DLOGV_IF(kTagRotator, "Acquire new session Output: width = %d, height = %d, format = %d, " \
-             "session_id %d", hw_rotator_session->output_buffer.width,
+             "session_id %d, client_id %d", hw_rotator_session->output_buffer.width,
              hw_rotator_session->output_buffer.height, hw_rotator_session->output_buffer.format,
-             hw_rotator_session->session_id);
+             hw_rotator_session->session_id, client_id);
 
     return kErrorNone;
   }
 
-  hw_rotator_session->output_buffer.width = input_config.dst_width;
-  hw_rotator_session->output_buffer.height = input_config.dst_height;
-  hw_rotator_session->output_buffer.format = input_config.dst_format;
-  hw_rotator_session->output_buffer.flags.secure = input_config.secure;
-  hw_rotator_session->session_id = acquired_session;
+  *hw_rotator_session = session_list_[acquired_session].hw_rotator_session;
 
   DLOGV_IF(kTagRotator, "Acquire existing session Output: width = %d, height = %d, format = %d, " \
-           "session_id %d", hw_rotator_session->output_buffer.width,
+           "session_id %d, client_id %d", hw_rotator_session->output_buffer.width,
            hw_rotator_session->output_buffer.height, hw_rotator_session->output_buffer.format,
-           hw_rotator_session->session_id);
+           hw_rotator_session->session_id, client_id);
 
   return kErrorNone;
 }
 
-DisplayError SessionManager::GetNextBuffer(HWRotatorSession *hw_rotator_session) {
+DisplayError SessionManager::GetNextBuffer(const int &client_id,
+                                           HWRotatorSession *hw_rotator_session) {
+  SCOPE_LOCK(locker_);
+
   DisplayError error = kErrorNone;
 
   int session_id = hw_rotator_session->session_id;
@@ -166,7 +169,7 @@
   Session *session = &session_list_[session_id];
   if (session->state != kSessionAcquired) {
     DLOGE("Invalid session state %d", session->state);
-    kErrorParameters;
+    return kErrorParameters;
   }
 
   uint32_t curr_index = session->curr_index;
@@ -195,33 +198,38 @@
   hw_rotator_session->output_buffer.planes[0].fd = buffer_info->alloc_buffer_info.fd;
   hw_rotator_session->output_buffer.planes[0].offset = session->offset[curr_index];
 
+  session->hw_rotator_session = *hw_rotator_session;
+
   DLOGI_IF(kTagRotator, "Output: width = %d, height = %d, format = %d, stride %d, " \
-           "curr_index = %d, offset %d, fd %d, session_id %d,",
+           "curr_index = %d, offset %d, fd %d, session_id %d, client_id %d",
            hw_rotator_session->output_buffer.width, hw_rotator_session->output_buffer.height,
            hw_rotator_session->output_buffer.format,
            hw_rotator_session->output_buffer.planes[0].stride, curr_index,
            hw_rotator_session->output_buffer.planes[0].offset,
-           hw_rotator_session->output_buffer.planes[0].fd, hw_rotator_session->session_id);
+           hw_rotator_session->output_buffer.planes[0].fd, session_id, client_id);
 
   return kErrorNone;
 }
 
-DisplayError SessionManager::Stop() {
+DisplayError SessionManager::Stop(const int &client_id) {
+  SCOPE_LOCK(locker_);
+
   DisplayError error = kErrorNone;
   uint32_t session_id = 0;
 
   // Release all the sessions which were not acquired in the current cycle and deallocate the
   // buffers associated with it.
   while ((active_session_count_ > 0) && (session_id < kMaxSessionCount)) {
-    if (session_list_[session_id].state == kSessionReady) {
+    if (session_list_[session_id].state == kSessionReady &&
+        session_list_[session_id].client_id == client_id) {
       error = ReleaseSession(&session_list_[session_id]);
       if (error != kErrorNone) {
         return error;
       }
       active_session_count_--;
 
-      DLOGI_IF(kTagRotator, "session_id = %d, active_session_count = %d", session_id,
-               active_session_count_);
+      DLOGI_IF(kTagRotator, "session_id = %d, active_session_count = %d, client_id %d", session_id,
+               active_session_count_, client_id);
     }
     session_id++;
   }
@@ -229,7 +237,10 @@
   return kErrorNone;
 }
 
-DisplayError SessionManager::SetReleaseFd(HWRotatorSession *hw_rotator_session) {
+DisplayError SessionManager::SetReleaseFd(const int &client_id,
+                                          HWRotatorSession *hw_rotator_session) {
+  SCOPE_LOCK(locker_);
+
   int session_id = hw_rotator_session->session_id;
   if (session_id > kMaxSessionCount) {
     return kErrorParameters;
@@ -238,7 +249,7 @@
   Session *session = &session_list_[session_id];
   if (session->state != kSessionAcquired) {
     DLOGE("Invalid session state %d", session->state);
-    kErrorParameters;
+    return kErrorParameters;
   }
 
   uint32_t &curr_index = session->curr_index;
@@ -251,8 +262,8 @@
 
   curr_index = (curr_index + 1) % buffer_count;
 
-  DLOGI_IF(kTagRotator, "session_id %d, curr_index = %d, release fd %d", session_id,
-           curr_index, hw_rotator_session->output_buffer.release_fence_fd);
+  DLOGI_IF(kTagRotator, "session_id %d, curr_index = %d, release fd %d, client_id %d", session_id,
+           curr_index, hw_rotator_session->output_buffer.release_fence_fd, client_id);
 
   return kErrorNone;
 }
@@ -333,7 +344,9 @@
       session->release_fd[idx] = -1;
     }
   }
+
   session->state = kSessionReleased;
+  session->client_id == -1;
 
   if (session->offset) {
     delete[] session->offset;
diff --git a/displayengine/libs/core/session_manager.h b/displayengine/libs/core/session_manager.h
index b27ba8b..3324c3e 100644
--- a/displayengine/libs/core/session_manager.h
+++ b/displayengine/libs/core/session_manager.h
@@ -43,11 +43,11 @@
   SessionManager(HWRotatorInterface *hw_intf, BufferAllocator *buffer_allocator,
                  BufferSyncHandler *buffer_sync_handler);
 
-  void Start();
-  DisplayError Stop();
-  DisplayError OpenSession(HWRotatorSession *hw_rotator_session);
-  DisplayError GetNextBuffer(HWRotatorSession *hw_rotator_session);
-  DisplayError SetReleaseFd(HWRotatorSession *hw_rotator_session);
+  void Start(const int &client_id);
+  DisplayError Stop(const int &client_id);
+  DisplayError OpenSession(const int &client_id, HWRotatorSession *hw_rotator_session);
+  DisplayError GetNextBuffer(const int &client_id, HWRotatorSession *hw_rotator_session);
+  DisplayError SetReleaseFd(const int &client_id, HWRotatorSession *hw_rotator_session);
 
  private:
   // TODO(user): Read from hw capability instead of hardcoding
@@ -66,13 +66,16 @@
     int *release_fd;
     uint32_t *offset;
     uint32_t curr_index;
+    int client_id;
 
-    Session() : state(kSessionReleased), release_fd(NULL), offset(NULL), curr_index(0) { }
+    Session() : state(kSessionReleased), release_fd(NULL), offset(NULL), curr_index(0),
+                client_id(-1) { }
   };
 
   DisplayError AcquireSession(HWRotatorSession *hw_rotator_session, Session *session);
   DisplayError ReleaseSession(Session *session);
 
+  Locker locker_;
   Session session_list_[kMaxSessionCount];
   HWRotatorInterface *hw_rotator_intf_;
   BufferAllocator *buffer_allocator_;
diff --git a/displayengine/libs/hwc/hwc_buffer_allocator.cpp b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
index 2adfc3a..61d9913 100644
--- a/displayengine/libs/hwc/hwc_buffer_allocator.cpp
+++ b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
@@ -63,11 +63,6 @@
   int height = INT(buffer_config.height);
   int format;
 
-  error = SetHALFormat(buffer_config.format, &format);
-  if (error != 0) {
-    return kErrorParameters;
-  }
-
   if (buffer_config.secure) {
     alloc_flags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
     alloc_flags |= GRALLOC_USAGE_PROTECTED;
@@ -81,11 +76,16 @@
     alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
   }
 
+  error = SetBufferInfo(buffer_config.format, &format, &alloc_flags);
+  if (error != 0) {
+    return kErrorParameters;
+  }
+
   int aligned_width = 0, aligned_height = 0;
   uint32_t buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
                                                     aligned_width, aligned_height);
 
-  buffer_size = ROUND_UP((buffer_size * buffer_config.buffer_count), data.align);
+  buffer_size = ROUND_UP(buffer_size, data.align) * buffer_config.buffer_count;
 
   data.base = 0;
   data.fd = -1;
@@ -116,8 +116,9 @@
 
   AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
   MetaBufferInfo *meta_buffer_info = static_cast<MetaBufferInfo *> (buffer_info->private_data);
-  if ((alloc_buffer_info->fd < 0) || (meta_buffer_info->base_addr == NULL)) {
-    return kErrorNone;
+  if (alloc_buffer_info->fd < 0) {
+    DLOGE("Invalid parameters: fd %d", alloc_buffer_info->fd);
+    return kErrorParameters;
   }
 
   gralloc::IMemAlloc *memalloc = alloc_controller_->getAllocator(meta_buffer_info->alloc_type);
@@ -147,7 +148,7 @@
   return kErrorNone;
 }
 
-int HWCBufferAllocator::SetHALFormat(LayerBufferFormat format, int *target) {
+int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, int *flags) {
   switch (format) {
   case kFormatRGBA8888:                 *target = HAL_PIXEL_FORMAT_RGBA_8888;             break;
   case kFormatRGBX8888:                 *target = HAL_PIXEL_FORMAT_RGBX_8888;             break;
@@ -163,7 +164,18 @@
   case kFormatYCbCr420SPVenusUbwc:    *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC; break;
   case kFormatRGBA5551:                 *target = HAL_PIXEL_FORMAT_RGBA_5551;             break;
   case kFormatRGBA4444:                 *target = HAL_PIXEL_FORMAT_RGBA_4444;             break;
-
+  case kFormatRGBA8888Ubwc:
+    *target = HAL_PIXEL_FORMAT_RGBA_8888;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
+  case kFormatRGBX8888Ubwc:
+    *target = HAL_PIXEL_FORMAT_RGBX_8888;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
+  case kFormatRGB565Ubwc:
+    *target = HAL_PIXEL_FORMAT_RGB_565;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
   default:
     DLOGE("Unsupported format = 0x%x", format);
     return -EINVAL;
diff --git a/displayengine/libs/hwc/hwc_buffer_allocator.h b/displayengine/libs/hwc/hwc_buffer_allocator.h
index 123f04a..eb3d1fd 100644
--- a/displayengine/libs/hwc/hwc_buffer_allocator.h
+++ b/displayengine/libs/hwc/hwc_buffer_allocator.h
@@ -57,7 +57,7 @@
     void *base_addr;             //!< Specifies the base address of the allocated output buffer.
   };
 
-  int SetHALFormat(LayerBufferFormat format, int *target);
+  int SetBufferInfo(LayerBufferFormat format, int *target, int *flags);
 
   gralloc::IAllocController *alloc_controller_;
 };
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 124310a..8a73d3c 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -350,6 +350,14 @@
       if (meta_data && meta_data->operation & UPDATE_REFRESH_RATE) {
         layer.frame_rate = meta_data->refreshrate;
       }
+
+      if (meta_data && meta_data->operation == PP_PARAM_INTERLACED && meta_data->interlaced) {
+        layer_buffer->flags.interlace = true;
+      }
+
+      if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
+        layer_buffer->flags.secure_display = true;
+      }
     }
 
     SetRect(hwc_layer.displayFrame, &layer.dst_rect);
@@ -625,6 +633,7 @@
   if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
     switch (source) {
     case HAL_PIXEL_FORMAT_RGBA_8888:          format = kFormatRGBA8888Ubwc;            break;
+    case HAL_PIXEL_FORMAT_RGBX_8888:          format = kFormatRGBX8888Ubwc;            break;
     case HAL_PIXEL_FORMAT_RGB_565:            format = kFormatRGB565Ubwc;              break;
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
@@ -755,6 +764,8 @@
     return "INTERLACE";
   case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
     return "YCbCr_420_SP_VENUS";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+    return "YCbCr_420_SP_VENUS_UBWC";
   default:
     return "Unknown pixel format";
   }
diff --git a/libgralloc/adreno_utils.h b/libgralloc/adreno_utils.h
index 78f49da..31f9d52 100644
--- a/libgralloc/adreno_utils.h
+++ b/libgralloc/adreno_utils.h
@@ -26,7 +26,7 @@
 typedef enum {
 
     ADRENO_PIXELFORMAT_UNKNOWN       = 0,
-    ADRENO_PIXELFORMAT_R8G8B8A8      = 27,
+    ADRENO_PIXELFORMAT_R8G8B8A8      = 28,
     ADRENO_PIXELFORMAT_R8G8B8A8_SRGB = 29,
     ADRENO_PIXELFORMAT_B5G6R5        = 85,
     ADRENO_PIXELFORMAT_B5G5R5A1      = 86,
@@ -37,6 +37,7 @@
     ADRENO_PIXELFORMAT_YUY2          = 107,
     ADRENO_PIXELFORMAT_B4G4R4A4      = 115,
     ADRENO_PIXELFORMAT_NV12_EXT      = 506,  // NV12 with non-std alignment and offsets
+    ADRENO_PIXELFORMAT_R8G8B8X8      = 507,  // GL_RGB8 (Internal)
     ADRENO_PIXELFORMAT_R8G8B8        = 508,  // GL_RGB8
     ADRENO_PIXELFORMAT_A1B5G5R5      = 519,  // GL_RGB5_A1
     ADRENO_PIXELFORMAT_R8G8B8X8_SRGB = 520,  // GL_SRGB8
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 3e17061..e37cddd 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -49,17 +49,28 @@
 
 #define ASTC_BLOCK_SIZE 16
 
-#ifdef ION_FLAG_CP_PIXEL
-#define CP_HEAP_ID ION_SECURE_HEAP_ID
-#else
+#ifndef ION_FLAG_CP_PIXEL
 #define ION_FLAG_CP_PIXEL 0
-#define CP_HEAP_ID ION_CP_MM_HEAP_ID
 #endif
 
 #ifndef ION_FLAG_ALLOW_NON_CONTIG
 #define ION_FLAG_ALLOW_NON_CONTIG 0
 #endif
 
+#ifdef MASTER_SIDE_CP
+#define CP_HEAP_ID ION_SECURE_HEAP_ID
+/* Please Add the new SD ION Heap here */
+#define SD_HEAP_ID 0
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_CP_PIXEL)
+/* Please Add the new SD ION Flag here */
+#define ION_SD_FLAGS ION_SECURE
+#else // SLAVE_SIDE_CP
+#define CP_HEAP_ID ION_CP_MM_HEAP_ID
+#define SD_HEAP_ID CP_HEAP_ID
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_ALLOW_NON_CONTIG)
+#define ION_SD_FLAGS ION_SECURE
+#endif
+
 using namespace gralloc;
 using namespace qdutils;
 
@@ -108,6 +119,16 @@
         *(void **)&LINK_adreno_isUBWCSupportedByGpu =
                 ::dlsym(libadreno_utils, "isUBWCSupportedByGpu");
     }
+
+    // Check if the overriding property debug.gralloc.gfx_ubwc_disable
+    // that disables UBWC allocations for the graphics stack is set
+    gfx_ubwc_disable = 0;
+    char property[PROPERTY_VALUE_MAX];
+    property_get("debug.gralloc.gfx_ubwc_disable", property, "0");
+    if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+       !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+        gfx_ubwc_disable = 1;
+    }
 }
 
 AdrenoMemInfo::~AdrenoMemInfo()
@@ -282,7 +303,7 @@
 
 int AdrenoMemInfo::isUBWCSupportedByGPU(int format)
 {
-    if (libadreno_utils) {
+    if (!gfx_ubwc_disable && libadreno_utils) {
         if (LINK_adreno_isUBWCSupportedByGpu) {
             ADRENOPIXELFORMAT gpu_format = getGpuPixelFormat(format);
             return LINK_adreno_isUBWCSupportedByGpu(gpu_format);
@@ -296,6 +317,8 @@
     switch (hal_format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
             return ADRENO_PIXELFORMAT_R8G8B8A8;
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+            return ADRENO_PIXELFORMAT_R8G8B8X8;
         case HAL_PIXEL_FORMAT_RGB_565:
             return ADRENO_PIXELFORMAT_B5G6R5;
         case HAL_PIXEL_FORMAT_sRGB_A_8888:
@@ -345,21 +368,16 @@
 
     if(usage & GRALLOC_USAGE_PROTECTED) {
         if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
-            ionHeapId = ION_HEAP(CP_HEAP_ID);
-            ionFlags |= ION_SECURE;
             if (usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
+                ionHeapId = ION_HEAP(SD_HEAP_ID);
                 /*
                  * There is currently no flag in ION for Secure Display
-                 * VM. Please add it here once available.
-                 *
-                   ionFlags |= <Ion flag for Secure Display>;
+                 * VM. Please add it to the define once available.
                 */
+                ionFlags |= ION_SD_FLAGS;
             } else {
-                ionFlags |= ION_FLAG_CP_PIXEL;
-            }
-
-            if (!(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY)) {
-                ionFlags |= ION_FLAG_ALLOW_NON_CONTIG;
+                ionHeapId = ION_HEAP(CP_HEAP_ID);
+                ionFlags |= ION_CP_FLAGS;
             }
         } else {
             // for targets/OEMs which do not need HW level protection
@@ -787,6 +805,7 @@
     {
         case HAL_PIXEL_FORMAT_RGB_565:
         case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
         case HAL_PIXEL_FORMAT_sRGB_A_8888:
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
         case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
@@ -893,6 +912,7 @@
             size += getUBwcMetaBufferSize(width, height, 2);
             break;
         case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
         case HAL_PIXEL_FORMAT_sRGB_A_8888:
             size = alignedw * alignedh * 4;
             size += getUBwcMetaBufferSize(width, height, 4);
@@ -908,3 +928,38 @@
     }
     return size;
 }
+
+int getRgbDataAddress(private_handle_t* hnd, void* rgb_data)
+{
+    int err = 0;
+
+    // This api is for RGB* formats
+    if (hnd->format > HAL_PIXEL_FORMAT_sRGB_X_8888) {
+        return -EINVAL;
+    }
+
+    // linear buffer
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED)) {
+        rgb_data = (void*)hnd->base;
+        return err;
+    }
+
+    unsigned int meta_size = 0;
+    switch (hnd->format) {
+        case HAL_PIXEL_FORMAT_RGB_565:
+            meta_size = getUBwcMetaBufferSize(hnd->width, hnd->height, 2);
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_sRGB_A_8888:
+            meta_size = getUBwcMetaBufferSize(hnd->width, hnd->height, 4);
+            break;
+        default:
+            ALOGE("%s:Unsupported RGB format: 0x%x", __FUNCTION__, hnd->format);
+            err = -EINVAL;
+            break;
+    }
+
+    rgb_data = (void*)(hnd->base + meta_size);
+    return err;
+}
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index a6f7874..0fd6e3b 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -34,7 +34,7 @@
 #define SZ_1M 0x100000
 #define SZ_4K 0x1000
 
-#ifdef ION_FLAG_CP_PIXEL
+#ifdef MASTER_SIDE_CP
 #define SECURE_ALIGN SZ_4K
 #else
 #define SECURE_ALIGN SZ_1M
@@ -155,8 +155,8 @@
             flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
         }
 
-        if (AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format) &&
-            isUBwcEnabled(format, usage)) {
+        if (isUBwcEnabled(format, usage) &&
+            AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format)) {
             flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
         }
 
@@ -308,6 +308,25 @@
             grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
     }
 
+    bool useFbMem = false;
+    char property[PROPERTY_VALUE_MAX];
+    char isUBWC[PROPERTY_VALUE_MAX];
+    if (usage & GRALLOC_USAGE_HW_FB) {
+        if ((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+            (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+            (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+            useFbMem = true;
+        } else {
+            if (property_get("debug.gralloc.enable_fb_ubwc", isUBWC, NULL) > 0){
+                if ((!strncmp(isUBWC, "1", PROPERTY_VALUE_MAX)) ||
+                    (!strncasecmp(isUBWC, "true", PROPERTY_VALUE_MAX))) {
+                    // Allocate UBWC aligned framebuffer
+                    usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+                }
+            }
+        }
+    }
+
     getGrallocInformationFromFormat(grallocFormat, &bufferType);
     size = getBufferSizeAndDimensions(w, h, grallocFormat, usage, alignedw,
                    alignedh);
@@ -316,15 +335,6 @@
         return -EINVAL;
     size = (bufferSize >= size)? bufferSize : size;
 
-    bool useFbMem = false;
-    char property[PROPERTY_VALUE_MAX];
-    if((usage & GRALLOC_USAGE_HW_FB) &&
-       (property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
-       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
-        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
-        useFbMem = true;
-    }
-
     int err = 0;
     if(useFbMem) {
         err = gralloc_alloc_framebuffer(usage, pHandle);
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index 5ee0cf8..98b4eec 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -71,6 +71,7 @@
 int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage);
 void free_buffer(private_handle_t *hnd);
 int getYUVPlaneInfo(private_handle_t* pHnd, struct android_ycbcr* ycbcr);
+int getRgbDataAddress(private_handle_t* pHnd, void* rgb_data);
 
 // To query if UBWC is enabled, based on format and usage flags
 bool isUBwcEnabled(int format, int usage);
@@ -148,6 +149,8 @@
     ADRENOPIXELFORMAT getGpuPixelFormat(int hal_format);
 
     private:
+        // Overriding flag to disable UBWC alloc for graphics stack
+        int  gfx_ubwc_disable;
         // Pointer to the padding library.
         void *libadreno_utils;
 
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 676c3bc..6998296 100755
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -85,6 +85,7 @@
 #define GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO 7
 #define GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO 8
 #define GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG 9
+#define GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS 10
 
 /* OEM specific HAL formats */
 
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index bd2c735..7d4e8ce 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -442,6 +442,15 @@
                 res = 0;
             } break;
 
+        case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS:
+            {
+                private_handle_t* hnd = va_arg(args, private_handle_t*);
+                void* rgb_data = va_arg(args, void*);
+                if (!private_handle_t::validate(hnd)) {
+                    res = getRgbDataAddress(hnd, rgb_data);
+                }
+            } break;
+
         default:
             break;
     }
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 1fa40ce..093b950 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -284,8 +284,9 @@
 
     if (!ctx->mBootAnimCompleted)
         processBootAnimCompleted(ctx);
-    if (LIKELY(list && list->numHwLayers > 1) && ctx->dpyAttr[dpy].connected &&
-            (ctx->dpyAttr[dpy].isActive ||
+    if (LIKELY(list && (list->numHwLayers > 1 ||
+                    ctx->mMDP.version < qdutils::MDP_V4_0)) &&
+        ctx->dpyAttr[dpy].connected && (ctx->dpyAttr[dpy].isActive ||
              ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
             && !ctx->dpyAttr[dpy].isPause) {
 
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 208fd3e..00bd643 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -562,17 +562,13 @@
     mDirtyLayerIndex =  checkDirtyRect(ctx, list, dpy);
     ALOGD_IF (DEBUG_COPYBIT, "%s:Dirty Layer Index: %d",
                                        __FUNCTION__, mDirtyLayerIndex);
-    // repetitive frame will have mDirtyLayerIndex as NO_UPDATING_LAYER
-    if (mDirtyLayerIndex == NO_UPDATING_LAYER) {
-        ALOGD_IF (DEBUG_COPYBIT, "%s: No Updating Layers", __FUNCTION__);
-        return true;
-    }
 
     hwc_rect_t clearRegion = {0,0,0,0};
     mDirtyRect = list->hwLayers[last].displayFrame;
 
-    if (CBUtils::getuiClearRegion(list, clearRegion, layerProp,
-                                                       mDirtyLayerIndex)) {
+    if (mDirtyLayerIndex != NO_UPDATING_LAYER &&
+            CBUtils::getuiClearRegion(list, clearRegion, layerProp,
+                                                    mDirtyLayerIndex)) {
        int clear_w =  clearRegion.right -  clearRegion.left;
        int clear_h =  clearRegion.bottom - clearRegion.top;
        //mdp can't handle solid fill for one line
@@ -584,8 +580,13 @@
        }else
            clear(renderBuffer, clearRegion);
     }
-    if (mDirtyLayerIndex != -1)
-           mDirtyRect = list->hwLayers[mDirtyLayerIndex].displayFrame;
+    if (mDirtyLayerIndex != -1) {
+        if (mDirtyLayerIndex == NO_UPDATING_LAYER) {
+            mDirtyRect = clearRegion;
+        } else {
+            mDirtyRect = list->hwLayers[mDirtyLayerIndex].displayFrame;
+        }
+    }
 
     // numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
     for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 5bd7931..e2c4677 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -55,6 +55,7 @@
 int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
 int (*MDPComp::sPerfLockRelease)(int value) = NULL;
 int MDPComp::sPerfHintWindow = -1;
+float MDPComp::sDownscaleThreshold = 1.0;
 
 enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
 
@@ -212,6 +213,10 @@
         }
     }
 
+    if(property_get("persist.hwc.downscale_threshold", property, "1.0") > 0) {
+        sDownscaleThreshold = (float)atof(property);
+    }
+
     return true;
 }
 
@@ -430,6 +435,24 @@
         //More conditions here, sRGB+Blend etc
         return false;
     }
+
+    //In targets with fewer pipes, frequent composition switch between MDP/GPU
+    //can happen for a layer due to lack of pipes. When this switch happens
+    //continuously for RGB downscaled layer with downscale greater than
+    //threshold, it appears as flicker as output
+    //of MDP and GPU are different as they use different filters for downscale.
+    //To avoid this flicker, punt RGB downscaled layer with downscale greater
+    //than threshold value to GPU always.
+    if((sDownscaleThreshold > 1.0)) {
+        if(((not isYuvBuffer(hnd))
+                and (not isDownscaleWithinThreshold(layer,
+                        sDownscaleThreshold)))) {
+            ALOGD_IF(isDebug(), "%s: required downscale is greater than \
+                    threshold %f", __FUNCTION__, sDownscaleThreshold);
+            return false;
+        }
+    }
+
     return true;
 }
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index db68e82..5c43aa7 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -283,6 +283,7 @@
     static int (*sPerfLockAcquire)(int, int, int*, int);
     static int (*sPerfLockRelease)(int value);
     static int sPerfHintWindow;
+    static float sDownscaleThreshold;
 
 };
 
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index aeda428..79235ff 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -972,6 +972,27 @@
 
     return false;
 }
+
+bool isDownscaleWithinThreshold(hwc_layer_1_t const* layer, float threshold) {
+    hwc_rect_t displayFrame  = layer->displayFrame;
+    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+    int dst_w, dst_h, src_w, src_h;
+    float downscale = 1.0;
+    dst_w = displayFrame.right - displayFrame.left;
+    dst_h = displayFrame.bottom - displayFrame.top;
+    src_w = sourceCrop.right - sourceCrop.left;
+    src_h = sourceCrop.bottom - sourceCrop.top;
+    if(dst_w && dst_h) {
+        float w_scale = ((float)src_w / (float)dst_w);
+        float h_scale = ((float)src_h / (float)dst_h);
+
+        if((w_scale > threshold) or (h_scale > threshold))
+            return false;
+    }
+
+    return true;
+}
+
 bool needsScaling(hwc_layer_1_t const* layer) {
     int dst_w, dst_h, src_w, src_h;
     hwc_rect_t displayFrame  = layer->displayFrame;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index da0182b..4849baf 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -309,6 +309,7 @@
 bool isAlphaScaled(hwc_layer_1_t const* layer);
 bool needsScaling(hwc_layer_1_t const* layer);
 bool isDownscaleRequired(hwc_layer_1_t const* layer);
+bool isDownscaleWithinThreshold(hwc_layer_1_t const* layer, float threshold);
 bool needsScalingWithSplit(hwc_context_t* ctx, hwc_layer_1_t const* layer,
                            const int& dpy);
 void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index 113bd48..da24382 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -153,8 +153,6 @@
         return getPipe_8x52(pipeSpecs);
     } else if(MDPVersion::getInstance().is8994()) {
         return getPipe_8994(pipeSpecs);
-    } else if(MDPVersion::getInstance().is8992()) {
-        return getPipe_8992(pipeSpecs);
     }
 
     eDest dest = OV_INVALID;
@@ -261,13 +259,6 @@
     //supported since we at least need 1 round in between where the DMA is
     //unused
     eDest dest = OV_INVALID;
-
-    // Reset format type to FORMAT_NONE to select the pipe irrespective of the
-    // format specifed by the client. This is required for the device where
-    // SMP starvation is unlikely, we need not keep track of formats
-    // programmed in the pipes to avoid potential pipe crunching.
-    resetPipeBookFormat(pipeSpecs.dpy);
-
     if(pipeSpecs.formatClass == FORMAT_YUV) {
         return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
     } else {
@@ -279,14 +270,9 @@
             dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
         }
     }
-
     return dest;
 }
 
-utils::eDest Overlay::getPipe_8992(const PipeSpecs& pipeSpecs) {
-    return getPipe_8994(pipeSpecs);
-}
-
 void Overlay::endAllSessions() {
     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
         if(mPipeBook[i].valid() && mPipeBook[i].mSession==PipeBook::START)
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 2782fc2..affb4db 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -179,9 +179,6 @@
     utils::eDest getPipe_8x39(const PipeSpecs& pipeSpecs);
     utils::eDest getPipe_8x52(const PipeSpecs& pipeSpecs);
     utils::eDest getPipe_8994(const PipeSpecs& pipeSpecs);
-    utils::eDest getPipe_8992(const PipeSpecs& pipeSpecs);
-
-    void resetPipeBookFormat(const int &dpy);
 
     /* Returns the handle to libscale.so's programScale function */
     static int (*getFnProgramScale())(struct mdp_overlay_list *);
@@ -448,14 +445,6 @@
     return "Invalid";
 }
 
-inline void Overlay::resetPipeBookFormat(const int &dpy) {
-    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
-        if (mPipeBook[i].mDisplay == dpy) {
-            mPipeBook[i].mFormatType = FORMAT_NONE;
-        }
-    }
-}
-
 }; // overlay
 
 #endif // OVERLAY_H
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 828f4fc..95bdc23 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -399,7 +399,7 @@
     int errVal = mdp_wrapper::validateAndSet(fbFd, list);
     if(errVal) {
         /* No dump for failure due to insufficient resource */
-        if(errVal != E2BIG) {
+        if(errVal != E2BIG && errVal != EBADSLT) {
             //ENODEV is returned when the driver cannot satisfy a pipe request.
             //This could happen if previous round's UNSET hasn't been commited
             //yet, either because of a missed vsync or because of difference in