Merge "sde: Remove redundant PostPrepare in Prepare function"
diff --git a/displayengine/include/core/debug_interface.h b/displayengine/include/core/debug_interface.h
index c90e1ff..ff72321 100644
--- a/displayengine/include/core/debug_interface.h
+++ b/displayengine/include/core/debug_interface.h
@@ -48,6 +48,7 @@
   kTagDriverConfig,     //!< Debug log is tagged for driver config.
   kTagBufferManager,    //!< Debug log is tagged for buffer manager state transitions.
   kTagOfflineCtrl,      //!< Debug log is tagged for offline controller.
+  kTagScalar,           //!< Debug log is tagged for Scalar Helper.
 };
 
 /*! @brief Display debug handler class.
diff --git a/displayengine/libs/core/Android.mk b/displayengine/libs/core/Android.mk
index c4c3d87..b7d2478 100644
--- a/displayengine/libs/core/Android.mk
+++ b/displayengine/libs/core/Android.mk
@@ -4,11 +4,14 @@
 LOCAL_MODULE                  := libsde
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := hardware/qcom/display/displayengine/include/ \
-                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
-                                 $(TARGET_OUT_HEADERS)/scalar/inc
+                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
 LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
                                  -Wconversion -Wall -Werror \
                                  -DLOG_TAG=\"SDE\"
+ifeq ($(TARGET_USES_SCALAR), true)
+  LOCAL_C_INCLUDES  += $(TARGET_OUT_HEADERS)/scalar/inc
+  LOCAL_CFLAGS      += -DUSES_SCALAR
+endif
 LOCAL_SHARED_LIBRARIES        := libdl libsdeutils libcutils
 LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 LOCAL_SRC_FILES               := core_interface.cpp \
@@ -25,6 +28,7 @@
                                  hw_interface.cpp \
                                  hw_framebuffer.cpp \
                                  dump_impl.cpp \
-                                 buffer_manager.cpp
+                                 buffer_manager.cpp \
+                                 scalar_helper.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 73f371e..f3cdb8b 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -43,7 +43,7 @@
 #include <utils/debug.h>
 
 #include "hw_framebuffer.h"
-
+#include "scalar_helper.h"
 
 #define __CLASS__ "HWFrameBuffer"
 
@@ -706,14 +706,16 @@
           }
         }
 
-        if (pipe_info->scale_data.enable_pxl_ext) {
+        mdp_scale_data* mdp_scale = hw_display->GetScaleDataRef(mdp_layer_count);
+#ifdef USES_SCALAR
+        // Set the configured scale data for MDP driver
+        ScalarHelper::GetInstance()->SetScaleData(i, !count, mdp_scale);
+        if (mdp_scale->enable_pxl_ext) {
           if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f))
-            mdp_buffer.width = pipe_info->scale_data.src_width;
-          hw_display->SetScaleData(pipe_info->scale_data, mdp_layer_count);
+            ScalarHelper::GetInstance()->UpdateSrcWidth(i, !count, &mdp_buffer.width);
         }
-
-        // Send scale data to MDP driver
-        mdp_layer.scale = hw_display->GetScaleRef(mdp_layer_count);
+#endif
+        mdp_layer.scale = mdp_scale;
         mdp_layer_count++;
 
         DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
@@ -764,12 +766,34 @@
   mdp_commit.flags |= MDP_VALIDATE_LAYER;
   if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+    DumpLayerCommit(hw_display->mdp_disp_commit);
     return kErrorHardware;
   }
 
   return kErrorNone;
 }
 
+void HWFrameBuffer::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;
+
+  DLOGE("mdp_commt: 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,
+         mdp_commit.left_roi.w, mdp_commit.left_roi.h);
+  DLOGE("right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x,
+         mdp_commit.right_roi.y, mdp_commit.right_roi.w, mdp_commit.right_roi.h);
+  for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
+    DLOGE("mdp_commt: 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;
+    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;
+    DLOGE("dst rect: x = %d, y = %d, w = %d, h = %d",
+          dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
+  }
+}
+
 DisplayError HWFrameBuffer::DisplayCommit(HWContext *hw_context, HWLayers *hw_layers) {
   DTRACE_SCOPED();
 
@@ -857,6 +881,7 @@
   mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
   if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+    DumpLayerCommit(hw_display->mdp_disp_commit);
     return kErrorHardware;
   }
 
@@ -1090,6 +1115,7 @@
       mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
       if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
         IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+        DumpLayerCommit(hw_display->mdp_disp_commit);
         return kErrorHardware;
       }
     }
@@ -1152,6 +1178,7 @@
     *target = width * 3;
     break;
   case kFormatYCbCr420SemiPlanarVenus:
+  case kFormatYCbCr420SPVenusUbwc:
   case kFormatYCbCr420Planar:
   case kFormatYCrCb420Planar:
   case kFormatYCbCr420SemiPlanar:
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index 68a0674..b2a37ab 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -89,36 +89,7 @@
       mdp_disp_commit.commit_v1.retire_fence = -1;
     }
 
-    mdp_scale_data* GetScaleRef(uint32_t index) { return &scale_data[index]; }
-
-    void SetScaleData(scalar::Scale scale, uint32_t index) {
-      mdp_scale_data *mdp_scale = &scale_data[index];
-      mdp_scale->enable_pxl_ext = scale.enable_pxl_ext;
-
-      for (int i = 0; i < MAX_PLANES; i++) {
-        mdp_scale->init_phase_x[i] = scale.init_phase_x[i];
-        mdp_scale->phase_step_x[i] = scale.phase_step_x[i];
-        mdp_scale->init_phase_y[i] = scale.init_phase_y[i];
-        mdp_scale->phase_step_y[i] = scale.phase_step_y[i];
-
-        mdp_scale->num_ext_pxls_left[i] = scale.left.extension[i];
-        mdp_scale->num_ext_pxls_top[i] = scale.top.extension[i];
-        mdp_scale->num_ext_pxls_right[i] = scale.right.extension[i];
-        mdp_scale->num_ext_pxls_btm[i] = scale.bottom.extension[i];
-
-        mdp_scale->left_ftch[i] = scale.left.overfetch[i];
-        mdp_scale->top_ftch[i] = scale.top.overfetch[i];
-        mdp_scale->right_ftch[i] = scale.right.overfetch[i];
-        mdp_scale->btm_ftch[i] = scale.bottom.overfetch[i];
-
-        mdp_scale->left_rpt[i] = scale.left.repeat[i];
-        mdp_scale->top_rpt[i] = scale.top.repeat[i];
-        mdp_scale->right_rpt[i] = scale.right.repeat[i];
-        mdp_scale->btm_rpt[i] = scale.bottom.repeat[i];
-
-        mdp_scale->roi_w[i] = scale.roi_width[i];
-      }
-    }
+    mdp_scale_data* GetScaleDataRef(uint32_t index) { return &scale_data[index]; }
   };
 
   struct HWRotator {
@@ -198,7 +169,7 @@
 
   DisplayError RotatorValidate(HWContext *device_ctx, HWLayers *hw_layers);
   DisplayError RotatorCommit(HWContext *device_ctx, HWLayers *hw_layers);
-
+  void DumpLayerCommit(mdp_layer_commit &layer_commit);
   inline DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
   inline DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
                                 uint32_t width, uint32_t *target);
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 9a60d8c..b92846f 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -30,7 +30,6 @@
 #include <utils/constants.h>
 #include <core/buffer_allocator.h>
 #include <core/buffer_sync_handler.h>
-#include <scalar.h>
 
 namespace sde {
 
@@ -131,7 +130,6 @@
   LayerRect dst_roi;
   uint8_t horizontal_decimation;
   uint8_t vertical_decimation;
-  scalar::Scale scale_data;
   bool valid;
   uint32_t z_order;
 
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 32d9891..1b5bb6d 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -31,17 +31,15 @@
 
 #define __CLASS__ "ResManager"
 
-using scalar::PipeInfo;
-using scalar::LayerInfo;
-
 namespace sde {
 
-void ResManager::RotationConfig(const LayerTransform &transform, const float &downscale,
-                                LayerRect *src_rect, struct HWLayerConfig *layer_config,
-                                uint32_t *rotate_count) {
+void ResManager::RotationConfig(LayerBufferFormat format, const LayerTransform &transform,
+                                const float &downscale, LayerRect *src_rect,
+                                struct HWLayerConfig *layer_config, uint32_t *rotate_count) {
   HWRotateInfo *rotate = &layer_config->rotates[0];
   float src_width = src_rect->right - src_rect->left;
   float src_height = src_rect->bottom - src_rect->top;
+  bool rot90 = IsRotationNeeded(transform.rotation);
   LayerRect dst_rect;
   // Rotate output is a temp buffer, always output to the top left corner for saving memory
   dst_rect.top = 0.0f;
@@ -50,7 +48,7 @@
   rotate->downscale_ratio = downscale;
 
   // downscale when doing rotation
-  if (IsRotationNeeded(transform.rotation)) {
+  if (rot90) {
     if (downscale > 1.0f) {
       src_height = ROUND_UP_ALIGN_DOWN(src_height, downscale);
       src_rect->bottom = src_rect->top + src_height;
@@ -74,6 +72,14 @@
   rotate->valid = true;
   rotate->dst_roi = dst_rect;
 
+  // Set WHF for Rotator output
+  LayerBufferFormat ouput_format;
+  SetRotatorOutputFormat(format, false /* bwc */, rot90, downscale, &ouput_format);
+  HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+  hw_buffer_info->buffer_config.format = ouput_format;
+  hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right);
+  hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom);
+
   *src_rect = dst_rect;
   layer_config->num_rotate = 1;
   (*rotate_count)++;
@@ -243,7 +249,8 @@
 
     LayerTransform transform = layer.transform;
     if (IsRotationNeeded(transform.rotation) || UINT32(rot_scale) != 1) {
-      RotationConfig(layer.transform, rot_scale, &src_rect, layer_config, rotate_count);
+      RotationConfig(layer.input_buffer->format, layer.transform, rot_scale, &src_rect,
+                     layer_config, rotate_count);
       // rotator will take care of flipping, reset tranform
       transform = LayerTransform();
     }
@@ -586,125 +593,6 @@
   }
 }
 
-// Scalar helper functions
-static void SetPipeInfo(HWPipeInfo* hw_pipe, PipeInfo* pipe) {
-  pipe->id = hw_pipe->pipe_id;
-  pipe->scale_data = &hw_pipe->scale_data;
-  pipe->horz_deci = hw_pipe->horizontal_decimation;
-  pipe->vert_deci = hw_pipe->vertical_decimation;
-
-  pipe->src_rect.x = UINT32(hw_pipe->src_roi.left);
-  pipe->src_rect.y = UINT32(hw_pipe->src_roi.top);
-  pipe->src_rect.w = UINT32(hw_pipe->src_roi.right) - pipe->src_rect.x;
-  pipe->src_rect.h = UINT32(hw_pipe->src_roi.bottom) - pipe->src_rect.y;
-
-  pipe->dst_rect.x = UINT32(hw_pipe->dst_roi.left);
-  pipe->dst_rect.y = UINT32(hw_pipe->dst_roi.top);
-  pipe->dst_rect.w = UINT32(hw_pipe->dst_roi.right) - pipe->dst_rect.x;
-  pipe->dst_rect.h = UINT32(hw_pipe->dst_roi.bottom) - pipe->dst_rect.y;
-}
-
-static void UpdateSrcRoi(PipeInfo* pipe, HWPipeInfo* hw_pipe) {
-  hw_pipe->src_roi.left   = FLOAT(pipe->src_rect.x);
-  hw_pipe->src_roi.top    = FLOAT(pipe->src_rect.y);
-  hw_pipe->src_roi.right  = FLOAT(pipe->src_rect.x + pipe->src_rect.w);
-  hw_pipe->src_roi.bottom = FLOAT(pipe->src_rect.y + pipe->src_rect.h);
-}
-
-static uint32_t GetScalarFormat(LayerBufferFormat source) {
-  uint32_t format = scalar::UNKNOWN_FORMAT;
-
-  switch (source) {
-  case kFormatARGB8888:                 format = scalar::ARGB_8888;         break;
-  case kFormatRGBA8888:                 format = scalar::RGBA_8888;         break;
-  case kFormatBGRA8888:                 format = scalar::BGRA_8888;         break;
-  case kFormatXRGB8888:                 format = scalar::XRGB_8888;         break;
-  case kFormatRGBX8888:                 format = scalar::RGBX_8888;         break;
-  case kFormatBGRX8888:                 format = scalar::BGRX_8888;         break;
-  case kFormatRGB888:                   format = scalar::RGB_888;           break;
-  case kFormatRGB565:                   format = scalar::RGB_565;           break;
-  case kFormatYCbCr420Planar:           format = scalar::Y_CB_CR_H2V2;      break;
-  case kFormatYCrCb420Planar:           format = scalar::Y_CR_CB_H2V2;      break;
-  case kFormatYCbCr420SemiPlanar:       format = scalar::Y_CBCR_H2V2;       break;
-  case kFormatYCrCb420SemiPlanar:       format = scalar::Y_CRCB_H2V2;       break;
-  case kFormatYCbCr422Packed:           format = scalar::YCBYCR_H2V1;       break;
-  case kFormatYCbCr420SemiPlanarVenus:  format = scalar::Y_CBCR_H2V2_VENUS; break;
-  case kFormatRGBA8888Ubwc:             format = scalar::RGBA_8888_UBWC;    break;
-  case kFormatRGB565Ubwc:               format = scalar::RGB_565_UBWC;      break;
-  case kFormatYCbCr420SPVenusUbwc:      format = scalar::Y_CBCR_H2V2_UBWC;  break;
-  default:
-    DLOGE("Unsupported source format: %x", source);
-    break;
-  }
-
-  return format;
-}
-
-bool ResManager::ConfigureScaling(HWLayers *hw_layers) {
-  HWLayersInfo &hw_layer_info = hw_layers->info;
-
-  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
-    Layer &layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
-    LayerBuffer *input_buffer = layer.input_buffer;
-    HWPipeInfo* left_pipe = &hw_layers->config[i].left_pipe;
-    HWPipeInfo* right_pipe = &hw_layers->config[i].right_pipe;
-
-    // Prepare data structure for lib scalar
-    uint32_t flags = 0;
-    struct LayerInfo layer_info;
-
-    if (layer.transform.rotation == 90.0f) {
-      // Flips will be taken care by rotator, if layer requires 90 rotation
-      flags |= scalar::SCALAR_SOURCE_ROTATED_90;
-    } else {
-      flags |= layer.transform.flip_vertical ? scalar::SCALAR_FLIP_UD : 0;
-      flags |= layer.transform.flip_horizontal ? scalar::SCALAR_FLIP_LR : 0;
-    }
-
-    for (uint32_t count = 0; count < 2; count++) {
-      HWPipeInfo* hw_pipe = (count == 0) ? left_pipe : right_pipe;
-      HWRotateInfo* rotate_info = &hw_layers->config[i].rotates[count];
-      PipeInfo* scalar_pipe = (count == 0) ? &layer_info.left_pipe : &layer_info.right_pipe;
-
-      if (rotate_info->valid)
-        input_buffer = &rotate_info->hw_buffer_info.output_buffer;
-
-      scalar_pipe->flags = flags;
-      hw_pipe->scale_data.src_width = input_buffer->width;
-      SetPipeInfo(hw_pipe, scalar_pipe);
-    }
-    layer_info.src_format = GetScalarFormat(input_buffer->format);
-
-    DLOGV_IF(kTagResources, "Scalar Input[%d] flags=%x format=%x", i, flags, layer_info.src_format);
-    DLOGV_IF(kTagResources, "Left: id=%d hD=%d vD=%d srcRect=[%d %d %d %d] dstRect=[%d %d %d %d]",
-        layer_info.left_pipe.id, layer_info.left_pipe.horz_deci, layer_info.left_pipe.vert_deci,
-        layer_info.left_pipe.src_rect.x, layer_info.left_pipe.src_rect.y,
-        layer_info.left_pipe.src_rect.w, layer_info.left_pipe.src_rect.h,
-        layer_info.left_pipe.dst_rect.x, layer_info.left_pipe.dst_rect.y,
-        layer_info.left_pipe.dst_rect.w, layer_info.left_pipe.dst_rect.h);
-    DLOGV_IF(kTagResources, "Right: id=%d hD=%d vD=%d srcRect=[%d %d %d %d] dstRect=[%d %d %d %d]",
-        layer_info.right_pipe.id, layer_info.right_pipe.horz_deci, layer_info.right_pipe.vert_deci,
-        layer_info.right_pipe.src_rect.x, layer_info.right_pipe.src_rect.y,
-        layer_info.right_pipe.src_rect.w, layer_info.right_pipe.src_rect.h,
-        layer_info.right_pipe.dst_rect.x, layer_info.right_pipe.dst_rect.y,
-        layer_info.right_pipe.dst_rect.w, layer_info.right_pipe.dst_rect.h);
-
-    // Configure scale data structure
-    if (ScalarConfigureScale(&layer_info) < 0) {
-      DLOGE("Scalar library failed to configure scale data!");
-      return false;
-    }
-
-    // Update Src Roi in HWPipeInfo
-    if (left_pipe->scale_data.enable_pxl_ext)
-      UpdateSrcRoi(&layer_info.left_pipe, left_pipe);
-    if (right_pipe->scale_data.enable_pxl_ext)
-      UpdateSrcRoi(&layer_info.right_pipe, right_pipe);
-  }
-
-  return true;
-}
-
 DisplayError ResManager::AlignPipeConfig(const Layer &layer, const LayerTransform &transform,
                                          HWPipeInfo *left_pipe, HWPipeInfo *right_pipe,
                                          uint32_t align_x, uint32_t align_y) {
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 336087e..dbb41e5 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -28,9 +28,9 @@
 #include <dlfcn.h>
 
 #include "res_manager.h"
+#include "scalar_helper.h"
 
 #define __CLASS__ "ResManager"
-#define SCALAR_LIBRARY_NAME "libscalar.so"
 
 namespace sde {
 
@@ -121,23 +121,16 @@
   rgb_pipes_[0].state = kPipeStateOwnedByKernel;
   rgb_pipes_[1].state = kPipeStateOwnedByKernel;
 
-  ScalarConfigureScale = NULL;
-  lib_scalar_handle_ = dlopen(SCALAR_LIBRARY_NAME, RTLD_NOW);
-  if (lib_scalar_handle_) {
-    void **scalar_func = reinterpret_cast<void **>(&ScalarConfigureScale);
-    *scalar_func = ::dlsym(lib_scalar_handle_, "configureScale");
-  } else {
-    DLOGW("Unable to load %s !", SCALAR_LIBRARY_NAME);
-  }
-
+#ifdef USES_SCALAR
+  ScalarHelper::GetInstance()->Init();
+#endif
   return kErrorNone;
 }
 
 DisplayError ResManager::Deinit() {
-  if (lib_scalar_handle_) {
-    dlclose(lib_scalar_handle_);
-    lib_scalar_handle_ = NULL;
-  }
+#ifdef USES_SCALAR
+  ScalarHelper::GetInstance()->Deinit();
+#endif
   return kErrorNone;
 }
 
@@ -392,24 +385,24 @@
              i, layer_config.left_pipe.pipe_id,  pipe_info->pipe_id);
   }
 
-  error = AllocRotatorBuffer(display_ctx, hw_layers);
-  if (error != kErrorNone) {
-    DLOGV_IF(kTagResources, "Rotator buffer allocation failed");
+#ifdef USES_SCALAR
+  if (!ScalarHelper::GetInstance()->ConfigureScale(hw_layers)) {
+    DLOGV_IF(kTagResources, "Scale data configuration has failed!");
     goto CleanupOnError;
   }
-
-  if (lib_scalar_handle_ && ScalarConfigureScale) {
-    if (!ConfigureScaling(hw_layers)) {
-      DLOGV_IF(kTagResources, "Scale data configuration has failed!");
-      goto CleanupOnError;
-    }
-  }
+#endif
 
   if (!CheckBandwidth(display_resource_ctx, hw_layers)) {
     DLOGV_IF(kTagResources, "Bandwidth check failed!");
     goto CleanupOnError;
   }
 
+  error = AllocRotatorBuffer(display_ctx, hw_layers);
+  if (error != kErrorNone) {
+    DLOGV_IF(kTagResources, "Rotator buffer allocation failed");
+    goto CleanupOnError;
+  }
+
   return kErrorNone;
 
 CleanupOnError:
@@ -628,6 +621,7 @@
     case kFormatYCbCr420SemiPlanar:
     case kFormatYCrCb420SemiPlanar:
     case kFormatYCbCr420SemiPlanarVenus:
+    case kFormatYCbCr420SPVenusUbwc:
       return 1.5f;
     default:
       DLOGE("GetBpp: Invalid buffer format: %x", format);
@@ -650,16 +644,9 @@
   for (uint32_t i = 0; i < layer_info.count; i++) {
     Layer& layer = layer_info.stack->layers[layer_info.index[i]];
     HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
-    bool rot90 = (layer.transform.rotation == 90.0f);
 
     if (rotate->valid) {
-      LayerBufferFormat rot_ouput_format;
-      SetRotatorOutputFormat(layer.input_buffer->format, false, rot90, &rot_ouput_format);
-
       HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
-      hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right - rotate->dst_roi.left);
-      hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom - rotate->dst_roi.top);
-      hw_buffer_info->buffer_config.format = rot_ouput_format;
       // Allocate two rotator output buffers by default for double buffering.
       hw_buffer_info->buffer_config.buffer_count = 2;
       hw_buffer_info->buffer_config.secure = layer.input_buffer->flags.secure;
@@ -672,13 +659,7 @@
 
     rotate = &hw_layers->config[i].rotates[1];
     if (rotate->valid) {
-      LayerBufferFormat rot_ouput_format;
-      SetRotatorOutputFormat(layer.input_buffer->format, false, rot90, &rot_ouput_format);
-
       HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
-      hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right - rotate->dst_roi.left);
-      hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom - rotate->dst_roi.top);
-      hw_buffer_info->buffer_config.format = rot_ouput_format;
       // Allocate two rotator output buffers by default for double buffering.
       hw_buffer_info->buffer_config.buffer_count = 2;
       hw_buffer_info->buffer_config.secure = layer.input_buffer->flags.secure;
@@ -1100,33 +1081,32 @@
 }
 
 void ResManager::SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
-                                        LayerBufferFormat *output_format) {
+                                        bool downscale, LayerBufferFormat *output_format) {
+  *output_format = input_format;
+
   switch (input_format) {
   case kFormatRGB565:
     if (rot90)
       *output_format = kFormatRGB888;
-    else
-      *output_format = input_format;
     break;
   case kFormatRGBA8888:
     if (bwc)
       *output_format = kFormatBGRA8888;
-    else
-      *output_format = input_format;
     break;
   case kFormatYCbCr420SemiPlanarVenus:
   case kFormatYCbCr420SemiPlanar:
     if (rot90)
       *output_format = kFormatYCrCb420SemiPlanar;
-    else
-      *output_format = input_format;
+    break;
+  case kFormatYCbCr420SPVenusUbwc:
+    if (downscale)
+      *output_format = kFormatYCrCb420SemiPlanar;
     break;
   case kFormatYCbCr420Planar:
   case kFormatYCrCb420Planar:
     *output_format = kFormatYCrCb420SemiPlanar;
     break;
   default:
-    *output_format = input_format;
     break;
   }
 
@@ -1136,8 +1116,5 @@
   return;
 }
 
-void* ResManager::lib_scalar_handle_ = NULL;
-int (*ResManager::ScalarConfigureScale)(struct scalar::LayerInfo* layer) = NULL;
-
 }  // namespace sde
 
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 0244cfb..be785c1 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -194,17 +194,16 @@
   bool IsYuvFormat(LayerBufferFormat format) { return (format >= kFormatYCbCr420Planar); }
   bool IsRotationNeeded(float rotation)
          { return (UINT32(rotation) == 90 || UINT32(rotation) == 270); }
-  void RotationConfig(const LayerTransform &transform, const float &downscale,
-                      LayerRect *src_rect, struct HWLayerConfig *layer_config,
-                      uint32_t *rotate_count);
+  void RotationConfig(LayerBufferFormat format, const LayerTransform &transform,
+                      const float &downscale, LayerRect *src_rect,
+                      struct HWLayerConfig *layer_config, uint32_t *rotate_count);
   DisplayError AcquireRotator(DisplayResourceContext *display_resource_ctx,
                               const uint32_t roate_cnt);
   void AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_cnt);
   void ClearRotator(DisplayResourceContext *display_resource_ctx);
   DisplayError AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers);
   void SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
-                              LayerBufferFormat *output_format);
-  bool ConfigureScaling(HWLayers *hw_layers);
+                              bool downscale, LayerBufferFormat *output_format);
   DisplayError AlignPipeConfig(const Layer &layer, const LayerTransform &transform,
                                HWPipeInfo *left_pipe, HWPipeInfo *right_pipe,
                                uint32_t align_x, uint32_t align_y);
@@ -227,8 +226,6 @@
   BufferAllocator *buffer_allocator_;
   BufferSyncHandler *buffer_sync_handler_;  // Pointer to buffer sync handler that was defined by
                                             // the display engine's client
-  static void* lib_scalar_handle_;  // Scalar library handle
-  static int (*ScalarConfigureScale)(struct scalar::LayerInfo* layer);
   PropertySetting property_setting_;
 };
 
diff --git a/displayengine/libs/core/scalar_helper.cpp b/displayengine/libs/core/scalar_helper.cpp
new file mode 100755
index 0000000..22488b3
--- /dev/null
+++ b/displayengine/libs/core/scalar_helper.cpp
@@ -0,0 +1,231 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef USES_SCALAR
+
+#include <dlfcn.h>
+#include <utils/debug.h>
+#include "scalar_helper.h"
+
+#define __CLASS__ "ScalarHelper"
+
+namespace sde {
+
+ScalarHelper* ScalarHelper::scalar_helper_ = NULL;
+
+ScalarHelper* ScalarHelper::GetInstance() {
+  if (scalar_helper_ == NULL) {
+    scalar_helper_ = new ScalarHelper();
+  }
+  return scalar_helper_;
+}
+
+// Scalar helper functions
+static void SetPipeInfo(HWPipeInfo* hw_pipe, scalar::PipeInfo* pipe) {
+  pipe->id = hw_pipe->pipe_id;
+  pipe->horz_deci = hw_pipe->horizontal_decimation;
+  pipe->vert_deci = hw_pipe->vertical_decimation;
+
+  pipe->src_rect.x = UINT32(hw_pipe->src_roi.left);
+  pipe->src_rect.y = UINT32(hw_pipe->src_roi.top);
+  pipe->src_rect.w = UINT32(hw_pipe->src_roi.right) - pipe->src_rect.x;
+  pipe->src_rect.h = UINT32(hw_pipe->src_roi.bottom) - pipe->src_rect.y;
+
+  pipe->dst_rect.x = UINT32(hw_pipe->dst_roi.left);
+  pipe->dst_rect.y = UINT32(hw_pipe->dst_roi.top);
+  pipe->dst_rect.w = UINT32(hw_pipe->dst_roi.right) - pipe->dst_rect.x;
+  pipe->dst_rect.h = UINT32(hw_pipe->dst_roi.bottom) - pipe->dst_rect.y;
+}
+
+static void UpdateSrcRoi(scalar::PipeInfo* pipe, HWPipeInfo* hw_pipe) {
+  hw_pipe->src_roi.left   = FLOAT(pipe->src_rect.x);
+  hw_pipe->src_roi.top    = FLOAT(pipe->src_rect.y);
+  hw_pipe->src_roi.right  = FLOAT(pipe->src_rect.x + pipe->src_rect.w);
+  hw_pipe->src_roi.bottom = FLOAT(pipe->src_rect.y + pipe->src_rect.h);
+}
+
+static uint32_t GetScalarFormat(LayerBufferFormat source) {
+  uint32_t format = scalar::UNKNOWN_FORMAT;
+
+  switch (source) {
+  case kFormatARGB8888:                 format = scalar::ARGB_8888;         break;
+  case kFormatRGBA8888:                 format = scalar::RGBA_8888;         break;
+  case kFormatBGRA8888:                 format = scalar::BGRA_8888;         break;
+  case kFormatXRGB8888:                 format = scalar::XRGB_8888;         break;
+  case kFormatRGBX8888:                 format = scalar::RGBX_8888;         break;
+  case kFormatBGRX8888:                 format = scalar::BGRX_8888;         break;
+  case kFormatRGB888:                   format = scalar::RGB_888;           break;
+  case kFormatRGB565:                   format = scalar::RGB_565;           break;
+  case kFormatYCbCr420Planar:           format = scalar::Y_CB_CR_H2V2;      break;
+  case kFormatYCrCb420Planar:           format = scalar::Y_CR_CB_H2V2;      break;
+  case kFormatYCbCr420SemiPlanar:       format = scalar::Y_CBCR_H2V2;       break;
+  case kFormatYCrCb420SemiPlanar:       format = scalar::Y_CRCB_H2V2;       break;
+  case kFormatYCbCr422Packed:           format = scalar::YCBYCR_H2V1;       break;
+  case kFormatYCbCr420SemiPlanarVenus:  format = scalar::Y_CBCR_H2V2_VENUS; break;
+  case kFormatRGBA8888Ubwc:             format = scalar::RGBA_8888_UBWC;    break;
+  case kFormatRGB565Ubwc:               format = scalar::RGB_565_UBWC;      break;
+  case kFormatYCbCr420SPVenusUbwc:      format = scalar::Y_CBCR_H2V2_UBWC;  break;
+  default:
+    DLOGE("Unsupported source format: %x", source);
+    break;
+  }
+  return format;
+}
+
+void ScalarHelper::Init() {
+  lib_scalar_handle_   = NULL;
+  ScalarConfigureScale = NULL;
+
+  lib_scalar_handle_ = dlopen(SCALAR_LIBRARY_NAME, RTLD_NOW);
+  if (lib_scalar_handle_) {
+    void **scalar_func = reinterpret_cast<void **>(&ScalarConfigureScale);
+    *scalar_func = ::dlsym(lib_scalar_handle_, "configureScale");
+  } else {
+    DLOGW("Unable to load %s !", SCALAR_LIBRARY_NAME);
+  }
+}
+
+void ScalarHelper::Deinit() {
+  if (lib_scalar_handle_) {
+    dlclose(lib_scalar_handle_);
+    lib_scalar_handle_ = NULL;
+  }
+}
+
+bool ScalarHelper::ConfigureScale(HWLayers *hw_layers) {
+
+  if (!lib_scalar_handle_ || !ScalarConfigureScale) {
+    // No scalar library
+    return true;
+  }
+
+  // Reset scale data
+  memset(&scale_data_, 0, sizeof(scale_data_));
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer &layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+    uint32_t width = layer.input_buffer->width;
+    LayerBufferFormat format = layer.input_buffer->format;
+    HWPipeInfo* left_pipe = &hw_layers->config[i].left_pipe;
+    HWPipeInfo* right_pipe = &hw_layers->config[i].right_pipe;
+
+    // Prepare data structure for lib scalar
+    uint32_t flags = 0;
+    struct scalar::LayerInfo layer_info;
+
+    if (layer.transform.rotation == 90.0f) {
+      // Flips will be taken care by rotator, if layer requires 90 rotation
+      flags |= scalar::SCALAR_SOURCE_ROTATED_90;
+    } else {
+      flags |= layer.transform.flip_vertical ? scalar::SCALAR_FLIP_UD : 0;
+      flags |= layer.transform.flip_horizontal ? scalar::SCALAR_FLIP_LR : 0;
+    }
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWPipeInfo* hw_pipe = (count == 0) ? left_pipe : right_pipe;
+      HWRotateInfo* rotate_info = &hw_layers->config[i].rotates[count];
+      scalar::PipeInfo* pipe = (count == 0) ? &layer_info.left_pipe : &layer_info.right_pipe;
+
+      if (rotate_info->valid) {
+        width = rotate_info->hw_buffer_info.buffer_config.width;
+        format = rotate_info->hw_buffer_info.buffer_config.format;
+      }
+
+      pipe->flags = flags;
+      pipe->scale_data = GetScaleRef(i, !count);
+      pipe->scale_data->src_width = width;
+      SetPipeInfo(hw_pipe, pipe);
+    }
+    layer_info.src_format = GetScalarFormat(format);
+
+    DLOGV_IF(kTagScalar, "Scalar Input[%d] flags=%x format=%x", i, flags, layer_info.src_format);
+    DLOGV_IF(kTagScalar, "Left: id=%d hD=%d vD=%d srcRect=[%d %d %d %d] dstRect=[%d %d %d %d]",
+      layer_info.left_pipe.id, layer_info.left_pipe.horz_deci, layer_info.left_pipe.vert_deci,
+      layer_info.left_pipe.src_rect.x, layer_info.left_pipe.src_rect.y,
+      layer_info.left_pipe.src_rect.w, layer_info.left_pipe.src_rect.h,
+      layer_info.left_pipe.dst_rect.x, layer_info.left_pipe.dst_rect.y,
+      layer_info.left_pipe.dst_rect.w, layer_info.left_pipe.dst_rect.h);
+    DLOGV_IF(kTagScalar, "Right: id=%d hD=%d vD=%d srcRect=[%d %d %d %d] dstRect=[%d %d %d %d]",
+      layer_info.right_pipe.id, layer_info.right_pipe.horz_deci, layer_info.right_pipe.vert_deci,
+      layer_info.right_pipe.src_rect.x, layer_info.right_pipe.src_rect.y,
+      layer_info.right_pipe.src_rect.w, layer_info.right_pipe.src_rect.h,
+      layer_info.right_pipe.dst_rect.x, layer_info.right_pipe.dst_rect.y,
+      layer_info.right_pipe.dst_rect.w, layer_info.right_pipe.dst_rect.h);
+
+    // Configure scale data structure
+    if (ScalarConfigureScale(&layer_info) < 0) {
+      DLOGE("Scalar library failed to configure scale data!");
+      return false;
+    }
+
+    // Update Src Roi in HWPipeInfo
+    if (layer_info.left_pipe.scale_data->enable_pxl_ext)
+      UpdateSrcRoi(&layer_info.left_pipe, left_pipe);
+    if (layer_info.right_pipe.scale_data->enable_pxl_ext)
+      UpdateSrcRoi(&layer_info.right_pipe, right_pipe);
+  }
+  return true;
+}
+
+void ScalarHelper::UpdateSrcWidth(uint32_t index, bool left, uint32_t* width) {
+  *width = GetScaleRef(index, left)->src_width;
+}
+
+void ScalarHelper::SetScaleData(uint32_t index, bool left, mdp_scale_data* mdp_scale) {
+
+  if (!lib_scalar_handle_ || !ScalarConfigureScale)
+    return;
+
+  scalar::Scale* scale = GetScaleRef(index, left);
+  mdp_scale->enable_pxl_ext = scale->enable_pxl_ext;
+
+  for (int i = 0; i < MAX_PLANES; i++) {
+    mdp_scale->init_phase_x[i] = scale->init_phase_x[i];
+    mdp_scale->phase_step_x[i] = scale->phase_step_x[i];
+    mdp_scale->init_phase_y[i] = scale->init_phase_y[i];
+    mdp_scale->phase_step_y[i] = scale->phase_step_y[i];
+
+    mdp_scale->num_ext_pxls_left[i] = scale->left.extension[i];
+    mdp_scale->num_ext_pxls_top[i] = scale->top.extension[i];
+    mdp_scale->num_ext_pxls_right[i] = scale->right.extension[i];
+    mdp_scale->num_ext_pxls_btm[i] = scale->bottom.extension[i];
+
+    mdp_scale->left_ftch[i] = scale->left.overfetch[i];
+    mdp_scale->top_ftch[i] = scale->top.overfetch[i];
+    mdp_scale->right_ftch[i] = scale->right.overfetch[i];
+    mdp_scale->btm_ftch[i] = scale->bottom.overfetch[i];
+
+    mdp_scale->left_rpt[i] = scale->left.repeat[i];
+    mdp_scale->top_rpt[i] = scale->top.repeat[i];
+    mdp_scale->right_rpt[i] = scale->right.repeat[i];
+    mdp_scale->btm_rpt[i] = scale->bottom.repeat[i];
+
+    mdp_scale->roi_w[i] = scale->roi_width[i];
+  }
+}
+
+} // namespace sde
+
+#endif
diff --git a/displayengine/libs/core/scalar_helper.h b/displayengine/libs/core/scalar_helper.h
new file mode 100755
index 0000000..a54cb0c
--- /dev/null
+++ b/displayengine/libs/core/scalar_helper.h
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __SCALAR_HELPER_H__
+#define __SCALAR_HELPER_H__
+
+#ifdef USES_SCALAR
+
+#include <sys/types.h>
+#include <linux/msm_mdp_ext.h>
+#include <hw_interface.h>
+#include <scalar.h>
+
+#define SCALAR_LIBRARY_NAME "libscalar.so"
+
+namespace sde {
+
+class ScalarHelper {
+
+ public:
+  void Init();
+  void Deinit();
+  bool ConfigureScale(HWLayers *hw_layers);
+  void UpdateSrcWidth(uint32_t index, bool left, uint32_t* src_width);
+  void SetScaleData(uint32_t index, bool left, mdp_scale_data* mdp_scale);
+  static ScalarHelper* GetInstance();
+
+ private:
+  explicit ScalarHelper() { }
+  struct ScaleData {
+    scalar::Scale left_scale;
+    scalar::Scale right_scale;
+  };
+  struct ScaleData scale_data_[kMaxSDELayers];
+  void* lib_scalar_handle_;
+  int (*ScalarConfigureScale)(struct scalar::LayerInfo* layer);
+  scalar::Scale* GetScaleRef(uint32_t index, bool left) {
+    return (left ? &scale_data_[index].left_scale : &scale_data_[index].right_scale);
+  }
+  static ScalarHelper* scalar_helper_;  // Singleton Instance
+};
+
+}  // namespace sde
+
+#endif
+#endif  // __SCALAR_HELPER_H__
diff --git a/displayengine/libs/hwc/hwc_buffer_allocator.cpp b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
index d4f4bac..f2383b2 100644
--- a/displayengine/libs/hwc/hwc_buffer_allocator.cpp
+++ b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
@@ -159,6 +159,7 @@
   case kFormatYCbCr420SemiPlanar:       *target = HAL_PIXEL_FORMAT_YCbCr_420_SP;          break;
   case kFormatYCbCr422Packed:           *target = HAL_PIXEL_FORMAT_YCbCr_422_I;           break;
   case kFormatYCbCr420SemiPlanarVenus:  *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;    break;
+  case kFormatYCbCr420SPVenusUbwc:    *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC; break;
 
   default:
     DLOGE("Unsupported format = 0x%x", format);
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 9783896..02f0c7e 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -64,6 +64,7 @@
     int     relFence;
     struct  mdp_buf_sync sync;
     struct  blitReq list;
+    uint8_t dynamic_fps;
 };
 
 /**
@@ -122,6 +123,10 @@
     out->b = min(lhs->b, rhs->b);
 }
 
+static bool validateCopybitRect(struct copybit_rect_t *rect) {
+    return ((rect->b > rect->t) && (rect->r > rect->l)) ;
+}
+
 /** convert COPYBIT_FORMAT to MDP format */
 static int get_format(int format) {
     switch (format) {
@@ -161,7 +166,7 @@
     img->memory_id  = hnd->fd;
 }
 /** setup rectangles */
-static void set_rects(struct copybit_context_t *dev,
+static bool set_rects(struct copybit_context_t *dev,
                       struct mdp_blit_req *e,
                       const struct copybit_rect_t *dst,
                       const struct copybit_rect_t *src,
@@ -169,6 +174,9 @@
     struct copybit_rect_t clip;
     intersect(&clip, scissor, dst);
 
+    if (!validateCopybitRect(&clip))
+       return false;
+
     e->dst_rect.x  = clip.l;
     e->dst_rect.y  = clip.t;
     e->dst_rect.w  = clip.r - clip.l;
@@ -212,6 +220,7 @@
             e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
         }
     }
+    return true;
 }
 
 /** setup mdp request */
@@ -219,6 +228,7 @@
                       struct mdp_blit_req *req, int flags)
 {
     req->alpha = dev->mAlpha;
+    req->fps = dev->dynamic_fps;
     req->transp_mask = MDP_TRANSP_NOP;
     req->flags = dev->mFlags | flags;
     // check if we are blitting to f/b
@@ -250,7 +260,7 @@
         for (unsigned int i=0 ; i<l->count ; i++) {
             ALOGE("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
                   "    dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
-                  "    flags=%08x"
+                  "    flags=%08x, fps=%d"
                   ,
                   i,
                   l->req[i].src.width,
@@ -267,7 +277,8 @@
                   l->req[i].dst_rect.y,
                   l->req[i].dst_rect.w,
                   l->req[i].dst_rect.h,
-                  l->req[i].flags
+                  l->req[i].flags,
+                  l->req[i].fps
                  );
         }
 #endif
@@ -315,6 +326,9 @@
                 if (value >= 256)   value = 255;
                 ctx->mAlpha = (uint8_t)value;
                 break;
+            case COPYBIT_DYNAMIC_FPS:
+                ctx->dynamic_fps = (uint8_t)value;
+                break;
             case COPYBIT_DITHER:
                 if (value == COPYBIT_ENABLE) {
                     ctx->mFlags |= MDP_DITHER;
@@ -524,7 +538,8 @@
             set_infos(ctx, req, flags);
             set_image(&req->dst, dst);
             set_image(&req->src, src);
-            set_rects(ctx, req, dst_rect, src_rect, &clip);
+            if (set_rects(ctx, req, dst_rect, src_rect, &clip) == false)
+                continue;
 
             if (req->src_rect.w<=0 || req->src_rect.h<=0)
                 continue;
@@ -747,6 +762,9 @@
     ctx->device.flush_get_fence = flush_get_fence;
     ctx->device.clear = clear_copybit;
     ctx->mAlpha = MDP_ALPHA_NOP;
+    //dynamic_fps is zero means default
+    //panel refresh rate for driver.
+    ctx->dynamic_fps = 0;
     ctx->mFlags = 0;
     ctx->sync.flags = 0;
     ctx->relFence = -1;
diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h
index 6428023..1fc17ed 100644
--- a/libcopybit/copybit.h
+++ b/libcopybit/copybit.h
@@ -79,6 +79,7 @@
     /* FB height */
     COPYBIT_FRAMEBUFFER_HEIGHT = 8,
     COPYBIT_FG_LAYER = 9,
+    COPYBIT_DYNAMIC_FPS = 10,
 };
 
 /* values for copybit_set_parameter(COPYBIT_TRANSFORM) */
diff --git a/libhdmi/hdmi.cpp b/libhdmi/hdmi.cpp
index 1b2ffe0..fb6493a 100644
--- a/libhdmi/hdmi.cpp
+++ b/libhdmi/hdmi.cpp
@@ -412,8 +412,9 @@
     // for all the timing info read, get the best config
     for (int configIndex = 0; configIndex < mModeCount; configIndex++) {
         currentModeInfo = mDisplayConfigs[configIndex];
+        edidMode = mEDIDModes[configIndex];
 
-        if (!currentModeInfo.supported) {
+        if (!isValidMode(edidMode)) {
             ALOGD("%s EDID Mode %d is not supported", __FUNCTION__, edidMode);
             continue;
         }
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index bf59217..928f3b8 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -893,6 +893,7 @@
         dumpsys_log(aBuf, ovDump);
         ovDump[0] = '\0';
     }
+    dumpsys_log(aBuf, "Copybit::isAbcInUse=%d\n\n",isAbcInUse(ctx) ? 1 : 0);
     strlcpy(buff, aBuf.string(), buff_len);
 }
 
@@ -966,7 +967,11 @@
         memset(dev, 0, sizeof(*dev));
 
         //Initialize hwc context
-        initContext(dev);
+        status = initContext(dev);
+        if (status < 0) {
+            free(dev);
+            return status;
+        }
 
         //Setup HWC methods
         dev->device.common.tag          = HARDWARE_DEVICE_TAG;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 68f168a..7bb5f60 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -354,10 +354,18 @@
             dx = (float)dst_w/(float)src_w;
             dy = (float)dst_h/(float)src_h;
 
-            if (dx > MAX_SCALE_FACTOR || dx < MIN_SCALE_FACTOR)
+            float scale_factor_max = MAX_SCALE_FACTOR;
+            float scale_factor_min = MIN_SCALE_FACTOR;
+
+            if (isAlphaPresent(layer)) {
+               scale_factor_max = MAX_SCALE_FACTOR/4;
+               scale_factor_min = MIN_SCALE_FACTOR*4;
+            }
+
+            if (dx > scale_factor_max || dx < scale_factor_min)
                 return false;
 
-            if (dy > MAX_SCALE_FACTOR || dy < MIN_SCALE_FACTOR)
+            if (dy > scale_factor_max || dy < scale_factor_min)
                 return false;
         }
     }
@@ -810,7 +818,13 @@
         ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
         return -1;
     }
-
+    uint32_t dynamic_fps = 0;
+#ifdef DYNAMIC_FPS
+    MetaData_t *mdata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
+    if (mdata && (mdata->operation & UPDATE_REFRESH_RATE)) {
+       dynamic_fps  = roundOff(mdata->refreshrate);
+    }
+#endif
     // Set the copybit source:
     copybit_image_t src;
     src.w = getWidth(hnd);
@@ -1025,6 +1039,7 @@
                                               layerTransform);
     //TODO: once, we are able to read layer alpha, update this
     copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
+    copybit->set_parameter(copybit, COPYBIT_DYNAMIC_FPS, dynamic_fps);
     copybit->set_parameter(copybit, COPYBIT_BLEND_MODE,
                                               layer->blending);
     copybit->set_parameter(copybit, COPYBIT_DITHER,
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 4d94647..b387642 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -131,7 +131,7 @@
             //On 8994, 8992 due to hardware limitations, we disable bwc
             //when HDMI intf is active
             if((qdutils::MDPVersion::getInstance().is8994() or
-                qdutils::MDPVersion::getInstance().is8092()) and
+                qdutils::MDPVersion::getInstance().is8992()) and
                     qdutils::MDPVersion::getInstance().supportsBWC()) {
                 Locker::Autolock _l(ctx->mDrawLock);
                 ctx->mBWCEnabled = true;
@@ -151,7 +151,7 @@
             //On 8994, 8992 due to hardware limitations, we disable bwc
             //when HDMI intf is active
             if((qdutils::MDPVersion::getInstance().is8994() or
-                qdutils::MDPVersion::getInstance().is8092()) and
+                qdutils::MDPVersion::getInstance().is8992()) and
                     qdutils::MDPVersion::getInstance().supportsBWC()) {
                 Locker::Autolock _l(ctx->mDrawLock);
                 ctx->mBWCEnabled = false;
@@ -202,7 +202,15 @@
                         "uevent thread", __FUNCTION__);
                 ctx->mWfdSyncLock.unlock();
             }
-            ctx->mHDMIDisplay->configure();
+            // If FB open fails ignore this hotplug event
+            int error = ctx->mHDMIDisplay->configure();
+            if (error < 0) {
+                ALOGE("%s: Open Framebuffer for dpy = %d", __FUNCTION__, dpy);
+                ctx->mDrawLock.lock();
+                ctx->dpyAttr[dpy].isConfiguring = false;
+                ctx->mDrawLock.unlock();
+                break;
+            }
             ctx->mHDMIDisplay->activateDisplay();
 
             ctx->mDrawLock.lock();
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index d176cd3..9c94b2f 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -76,7 +76,7 @@
 #endif
 #endif
 
-#define PROP_DEFAULT_APPBUFFER  "sf.default.app_buffer_count"
+#define PROP_DEFAULT_APPBUFFER  "hw.sf.app_buff_count"
 #define MAX_RAM_SIZE  512*1024*1024
 #define qHD_WIDTH 540
 
@@ -266,8 +266,26 @@
     }
 }
 
-void initContext(hwc_context_t *ctx)
+int initContext(hwc_context_t *ctx)
 {
+    int error = -1;
+    int compositionType = 0;
+
+    //Right now hwc starts the service but anybody could do it, or it could be
+    //independent process as well.
+    QService::init();
+    sp<IQClient> client = new QClient(ctx);
+    sp<IQService> iqs = interface_cast<IQService>(
+            defaultServiceManager()->getService(
+            String16("display.qservice")));
+    if (iqs.get()) {
+      iqs->connect(client);
+      ctx->mQService = reinterpret_cast<QService* >(iqs.get());
+    } else {
+      ALOGE("%s: Failed to acquire service pointer", __FUNCTION__);
+      return error;
+    }
+
     overlay::Overlay::initOverlay();
     ctx->mHDMIDisplay = new HDMIDisplay();
     uint32_t priW = 0, priH = 0;
@@ -280,15 +298,24 @@
     if(ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
         int connected = ctx->mHDMIDisplay->getConnectedState();
         if(connected == 1) {
-            ctx->mHDMIDisplay->configure();
+            error = ctx->mHDMIDisplay->configure();
+            if (error < 0) {
+                goto OpenFBError;
+            }
             updateDisplayInfo(ctx, HWC_DISPLAY_PRIMARY);
             ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
         } else {
-            openFramebufferDevice(ctx);
+            error = openFramebufferDevice(ctx);
+            if(error < 0) {
+                goto OpenFBError;
+            }
             ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = false;
         }
     } else {
-        openFramebufferDevice(ctx);
+        error = openFramebufferDevice(ctx);
+        if(error < 0) {
+            goto OpenFBError;
+        }
         ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
         // Send the primary resolution to the hdmi display class
         // to be used for MDP scaling functionality
@@ -314,8 +341,8 @@
 
     // Check if the target supports copybit compostion (dyn/mdp) to
     // decide if we need to open the copybit module.
-    int compositionType =
-        qdutils::QCCompositionType::getInstance().getCompositionType();
+    compositionType =
+                qdutils::QCCompositionType::getInstance().getCompositionType();
 
     // Only MDP copybit is used
     if ((compositionType & (qdutils::COMPOSITION_TYPE_DYN |
@@ -372,21 +399,6 @@
     ctx->mExtOrientation = 0;
     ctx->numActiveDisplays = 1;
 
-    //Right now hwc starts the service but anybody could do it, or it could be
-    //independent process as well.
-    QService::init();
-    sp<IQClient> client = new QClient(ctx);
-    sp<IQService> iqs = interface_cast<IQService>(
-            defaultServiceManager()->getService(
-            String16("display.qservice")));
-    if (iqs.get()) {
-      iqs->connect(client);
-      ctx->mQService = reinterpret_cast<QService* >(iqs.get());
-    } else {
-      ALOGE("%s: Failed to acquire service pointer", __FUNCTION__);
-      return;
-    }
-
     // Initialize device orientation to its default orientation
     ctx->deviceOrientation = 0;
     ctx->mBufferMirrorMode = false;
@@ -428,6 +440,13 @@
     ctx->mHPDEnabled = false;
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
+
+    return 0;
+
+OpenFBError:
+    ALOGE("%s: Fatal Error: FB Open failed!!!", __FUNCTION__);
+    delete ctx->mHDMIDisplay;
+    return error;
 }
 
 void closeContext(hwc_context_t *ctx)
@@ -2932,7 +2951,11 @@
     // TODO: If HDMI is connected after the display has booted up,
     // and the best configuration is different from the default
     // then we need to deal with this appropriately.
-    ctx->mHDMIDisplay->configure();
+    int error = ctx->mHDMIDisplay->configure();
+    if (error < 0) {
+        ALOGE("Error opening FrameBuffer");
+        return;
+    }
     updateDisplayInfo(ctx, dpy);
     initCompositionResources(ctx, dpy);
     ctx->dpyAttr[dpy].connected = true;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 23157d4..ea8d652 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -280,7 +280,7 @@
 void dumpLayer(hwc_layer_1_t const* l);
 void setListStats(hwc_context_t *ctx, hwc_display_contents_1_t *list,
         int dpy);
-void initContext(hwc_context_t *ctx);
+int initContext(hwc_context_t *ctx);
 void closeContext(hwc_context_t *ctx);
 //Crops source buffer against destination and FB boundaries
 void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 1290f32..0c31dd3 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -353,8 +353,31 @@
     mdp_overlay* ovArray[count];
     memset(&ovArray, 0, sizeof(ovArray));
 
+    uint8_t max_horz_deci = 0, max_vert_deci = 0;
+
+    // Decimation factor for the left and right pipe differs, when there is a
+    // one pixel difference in the dst width of right pipe and the left pipe.
+    // libscalar returns a failure as it expects decimation on both the pipe
+    // to be same. So compare the decimation factor on both the pipes and assign
+    // the maximum of it.
     for(int i = 0; i < count; i++) {
-        ovArray[i] = &mdpCtrlArray[i]->mOVInfo;
+        mdp_overlay *ov_current = &mdpCtrlArray[i]->mOVInfo;
+        for(int j = i + 1; j < count; j++) {
+            mdp_overlay *ov_next = &mdpCtrlArray[j]->mOVInfo;
+            if(ov_current->z_order == ov_next->z_order) {
+                max_horz_deci = utils::max(ov_current->horz_deci,
+                                           ov_next->horz_deci);
+                max_vert_deci = utils::max(ov_current->vert_deci,
+                                           ov_next->vert_deci);
+
+                ov_current->horz_deci = max_horz_deci;
+                ov_next->horz_deci = max_horz_deci;
+                ov_current->vert_deci = max_vert_deci;
+                ov_next->vert_deci = max_vert_deci;
+                break;
+            }
+        }
+        ovArray[i] = ov_current;
     }
 
     struct mdp_overlay_list list;
diff --git a/libqservice/QService.cpp b/libqservice/QService.cpp
index 5276695..ddb4b18 100644
--- a/libqservice/QService.cpp
+++ b/libqservice/QService.cpp
@@ -64,11 +64,15 @@
     status_t err = (status_t) FAILED_TRANSACTION;
     IPCThreadState* ipc = IPCThreadState::self();
     //Rewind parcel in case we're calling from the same process
-    if (ipc->getCallingPid() == getpid())
+    bool sameProcess = (ipc->getCallingPid() == getpid());
+    if(sameProcess)
         inParcel->setDataPosition(0);
     if (mClient.get()) {
         ALOGD_IF(QSERVICE_DEBUG, "Dispatching command: %d", command);
         err = mClient->notifyCallback(command, inParcel, outParcel);
+        //Rewind parcel in case we're calling from the same process
+        if (sameProcess)
+            outParcel->setDataPosition(0);
     }
     return err;
 }