Merge "gralloc: Fix UBWC related issues"
diff --git a/displayengine/libs/core/fb/hw_device.cpp b/displayengine/libs/core/fb/hw_device.cpp
index 6db1370..d96820f 100644
--- a/displayengine/libs/core/fb/hw_device.cpp
+++ b/displayengine/libs/core/fb/hw_device.cpp
@@ -40,7 +40,6 @@
 #include <utils/debug.h>
 
 #include "hw_device.h"
-#include "scalar_helper.h"
 
 #define __CLASS__ "HWDevice"
 
@@ -249,17 +248,15 @@
         SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
         SetMDPFlags(layer, is_rotator_used, &mdp_layer.flags);
 
-        mdp_scale_data* mdp_scale = 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))
-            ScalarHelper::GetInstance()->UpdateSrcWidth(i, !count, &mdp_buffer.width);
+        if (pipe_info->scale_data.enable_pixel_ext) {
+          if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f)) {
+            mdp_buffer.width = pipe_info->scale_data.src_width;
+          }
+          SetHWScaleData(pipe_info->scale_data, mdp_layer_count);
         }
-#endif
-        mdp_layer.scale = mdp_scale;
 
+        // Send scale data to MDP driver
+        mdp_layer.scale = GetScaleDataRef(mdp_layer_count);
         mdp_layer_count++;
 
         DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
@@ -274,7 +271,7 @@
                  mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
         DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
                  mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
-        for (int j = 0; j < MAX_PLANES; j++) {
+        for (int j = 0; j < 4; j++) {
           DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
                  j, mdp_layer.scale->init_phase_x[j], mdp_layer.scale->phase_step_x[j],
                  mdp_layer.scale->init_phase_y[j], mdp_layer.scale->phase_step_y[j],
@@ -907,5 +904,36 @@
   mdp_disp_commit_.commit_v1.retire_fence = -1;
 }
 
+void HWDevice::SetHWScaleData(const ScaleData &scale, uint32_t index) {
+  mdp_scale_data *mdp_scale = GetScaleDataRef(index);
+  mdp_scale->enable_pxl_ext = scale.enable_pixel_ext;
+
+  for (int i = 0; i < 4; i++) {
+    const HWPlane &plane = scale.plane[i];
+    mdp_scale->init_phase_x[i] = plane.init_phase_x;
+    mdp_scale->phase_step_x[i] = plane.phase_step_x;
+    mdp_scale->init_phase_y[i] = plane.init_phase_y;
+    mdp_scale->phase_step_y[i] = plane.phase_step_y;
+
+    mdp_scale->num_ext_pxls_left[i] = plane.left.extension;
+    mdp_scale->left_ftch[i] = plane.left.overfetch;
+    mdp_scale->left_rpt[i] = plane.left.repeat;
+
+    mdp_scale->num_ext_pxls_top[i] = plane.top.extension;
+    mdp_scale->top_ftch[i] = plane.top.overfetch;
+    mdp_scale->top_rpt[i] = plane.top.repeat;
+
+    mdp_scale->num_ext_pxls_right[i] = plane.right.extension;
+    mdp_scale->right_ftch[i] = plane.right.overfetch;
+    mdp_scale->right_rpt[i] = plane.right.repeat;
+
+    mdp_scale->num_ext_pxls_btm[i] = plane.bottom.extension;
+    mdp_scale->btm_ftch[i] = plane.bottom.overfetch;
+    mdp_scale->btm_rpt[i] = plane.bottom.repeat;
+
+    mdp_scale->roi_w[i] = plane.roi_width;
+  }
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
index 734b69d..18c6652 100644
--- a/displayengine/libs/core/fb/hw_device.h
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -91,6 +91,7 @@
   void GetSplitInfo(int device_node, HWPanelInfo *panel_info);
   int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
   mdp_scale_data* GetScaleDataRef(uint32_t index) { return &scale_data_[index]; }
+  void SetHWScaleData(const ScaleData &scale, uint32_t index);
   void ResetDisplayParams();
 
   bool EnableHotPlugDetection(int enable);
diff --git a/displayengine/libs/core/fb/hw_hdmi.cpp b/displayengine/libs/core/fb/hw_hdmi.cpp
index 67fa2c6..d258df3 100644
--- a/displayengine/libs/core/fb/hw_hdmi.cpp
+++ b/displayengine/libs/core/fb/hw_hdmi.cpp
@@ -222,8 +222,9 @@
   display_attributes->y_pixels = timing_mode->active_v;
   display_attributes->v_total = timing_mode->active_v + timing_mode->front_porch_v +
       timing_mode->back_porch_v + timing_mode->pulse_width_v;
-  display_attributes->h_total = timing_mode->active_h + timing_mode->front_porch_h +
-      timing_mode->back_porch_h + timing_mode->pulse_width_h;
+  uint32_t h_blanking = timing_mode->front_porch_h + timing_mode->back_porch_h +
+      timing_mode->pulse_width_h;
+  display_attributes->h_total = timing_mode->active_h + h_blanking;
   display_attributes->x_dpi = 0;
   display_attributes->y_dpi = 0;
   display_attributes->fps = FLOAT(timing_mode->refresh_rate) / 1000.0f;
@@ -232,6 +233,7 @@
   if (display_attributes->x_pixels > hw_resource_.max_mixer_width) {
     display_attributes->is_device_split = true;
     display_attributes->split_left = display_attributes->x_pixels / 2;
+    display_attributes->h_total += h_blanking;
   }
   return kErrorNone;
 }
diff --git a/displayengine/libs/core/fb/hw_primary.cpp b/displayengine/libs/core/fb/hw_primary.cpp
index 7b9cbe0..87de5d4 100644
--- a/displayengine/libs/core/fb/hw_primary.cpp
+++ b/displayengine/libs/core/fb/hw_primary.cpp
@@ -191,8 +191,9 @@
   display_attributes->y_pixels = var_screeninfo.yres;
   display_attributes->v_total = var_screeninfo.yres + var_screeninfo.lower_margin +
       var_screeninfo.upper_margin + var_screeninfo.vsync_len;
-  display_attributes->h_total = var_screeninfo.xres + var_screeninfo.right_margin +
-      var_screeninfo.left_margin + var_screeninfo.hsync_len;
+  uint32_t h_blanking = var_screeninfo.right_margin + var_screeninfo.left_margin +
+      var_screeninfo.hsync_len;
+  display_attributes->h_total = var_screeninfo.xres + h_blanking;
   display_attributes->x_dpi =
       (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
   display_attributes->y_dpi =
@@ -204,6 +205,7 @@
   display_attributes->split_left = hw_panel_info_.split_info.left_split ?
       hw_panel_info_.split_info.left_split : display_attributes->x_pixels / 2;
   display_attributes->always_src_split = hw_panel_info_.split_info.always_src_split;
+  display_attributes->h_total += display_attributes->is_device_split ? h_blanking : 0;
 
   return kErrorNone;
 }
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 36cb85e..5610ccd 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -102,12 +102,45 @@
   HWRotatorSession() : hw_block_count(0), downscale_ratio(1.0f), session_id(-1) { }
 };
 
+struct HWPixelExtension {
+  // Number of pixels extension in left, right, top and bottom directions for all color components.
+  // This pixel value for each color component should be sum of fetch and repeat pixels.
+  int extension;
+
+  // Number of pixels need to be overfetched in left, right, top and bottom directions from source
+  // image for scaling.
+  int overfetch;
+
+  // Number of pixels need to be repeated in left, right, top and bottom directions for scaling.
+  int repeat;
+};
+
+struct HWPlane {
+  int init_phase_x;
+  int phase_step_x;
+  int init_phase_y;
+  int phase_step_y;
+  HWPixelExtension left;
+  HWPixelExtension top;
+  HWPixelExtension right;
+  HWPixelExtension bottom;
+  uint32_t roi_width;
+};
+
+struct ScaleData {
+  uint8_t enable_pixel_ext;
+  uint32_t src_width;
+  uint32_t src_height;
+  HWPlane plane[4];
+};
+
 struct HWPipeInfo {
   uint32_t pipe_id;
   LayerRect src_roi;
   LayerRect dst_roi;
   uint8_t horizontal_decimation;
   uint8_t vertical_decimation;
+  ScaleData scale_data;
   bool valid;
   uint32_t z_order;
 
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 261155f..7344c21 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -28,7 +28,6 @@
 #include <dlfcn.h>
 
 #include "res_manager.h"
-#include "scalar_helper.h"
 
 #define __CLASS__ "ResManager"
 
@@ -36,7 +35,7 @@
 
 ResManager::ResManager()
   : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), virtual_count_(0),
-    buffer_allocator_(NULL), buffer_sync_handler_(NULL) {
+    buffer_allocator_(NULL), buffer_sync_handler_(NULL), scalar_(NULL) {
 }
 
 DisplayError ResManager::Init(const HWResourceInfo &hw_res_info) {
@@ -110,18 +109,17 @@
   rgb_pipes_[0].state = kPipeStateOwnedByKernel;
   rgb_pipes_[1].state = kPipeStateOwnedByKernel;
 
-#ifdef USES_SCALAR
-  ScalarHelper::GetInstance()->Init();
-#endif
+  error = Scalar::CreateScalar(&scalar_);
+  if (error != kErrorNone) {
+    DLOGE("Failed to create Scalar object!");
+  }
 
   max_system_bw_ = FLOAT(hw_res_info_.max_bandwidth_high);
-  return kErrorNone;
+  return error;
 }
 
 DisplayError ResManager::Deinit() {
-#ifdef USES_SCALAR
-  ScalarHelper::GetInstance()->Deinit();
-#endif
+  Scalar::Destroy(scalar_);
   return kErrorNone;
 }
 
@@ -379,12 +377,10 @@
              i, layer_config.left_pipe.pipe_id,  pipe_info->pipe_id);
   }
 
-#ifdef USES_SCALAR
-  if (!ScalarHelper::GetInstance()->ConfigureScale(hw_layers)) {
+  if (scalar_->ConfigureScale(hw_layers) != kErrorNone) {
     DLOGV_IF(kTagResources, "Scale data configuration has failed!");
     goto CleanupOnError;
   }
-#endif
 
   if (!CheckBandwidth(display_resource_ctx, hw_layers)) {
     DLOGV_IF(kTagResources, "Bandwidth check failed!");
@@ -508,7 +504,15 @@
   // Command mode panel, data gets transferred from MDP to panel during blanking time as well,
   // which means MDP needs to fetch the data faster. So pipe bandwidth needs to be adjusted.
   if (display_ctx->hw_panel_info_.mode == kModeCommand) {
-    bw *= FLOAT(display_attributes.h_total) / FLOAT(display_attributes.x_pixels);
+    uint32_t h_total = display_attributes.h_total;
+    uint32_t h_active = display_attributes.x_pixels;
+    // On split-panel device, h_active is left split
+    if (display_attributes.is_device_split) {
+      uint32_t h_blanking = (h_total - h_active) / 2;
+      h_active = display_attributes.split_left;
+      h_total = h_active + h_blanking;
+    }
+    bw *= FLOAT(h_total) / FLOAT(h_active);
   }
 
   // Bandwidth in GBps
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 7fa5260..32eb6ea 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -31,6 +31,7 @@
 
 #include "hw_interface.h"
 #include "dump_impl.h"
+#include "scalar_helper.h"
 
 namespace sde {
 
@@ -231,6 +232,7 @@
   BufferSyncHandler *buffer_sync_handler_;  // Pointer to buffer sync handler that was defined by
                                             // the display engine's client
   PropertySetting property_setting_;
+  Scalar *scalar_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/scalar_helper.cpp b/displayengine/libs/core/scalar_helper.cpp
index b5d8989..e600b79 100644
--- a/displayengine/libs/core/scalar_helper.cpp
+++ b/displayengine/libs/core/scalar_helper.cpp
@@ -22,8 +22,6 @@
 * 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"
@@ -32,40 +30,94 @@
 
 namespace sde {
 
-ScalarHelper* ScalarHelper::scalar_helper_ = NULL;
+#ifdef USES_SCALAR
+ScalarHelper::ScalarHelper()
+  : scalar_library_name_("libscalar.so"), configure_scale_api_("configureScale"),
+    lib_scalar_(NULL), configure_scale_(NULL) {
+}
 
-ScalarHelper* ScalarHelper::GetInstance() {
-  if (scalar_helper_ == NULL) {
-    scalar_helper_ = new ScalarHelper();
+DisplayError ScalarHelper::Init() {
+  lib_scalar_ = dlopen(scalar_library_name_, RTLD_NOW);
+  if (lib_scalar_) {
+    void **scalar_func = reinterpret_cast<void **>(&configure_scale_);
+    *scalar_func = ::dlsym(lib_scalar_, configure_scale_api_);
+    if (!configure_scale_) {
+      DLOGE("Unable to find symbol for %s API!", configure_scale_api_);
+      dlclose(lib_scalar_);
+      return kErrorUndefined;
+    }
+  } else {
+    DLOGW("Unable to load %s !", scalar_library_name_);
+    return kErrorNotSupported;
   }
-  return scalar_helper_;
+
+  return kErrorNone;
 }
 
-// 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;
+void ScalarHelper::Deinit() {
+  if (lib_scalar_) {
+    dlclose(lib_scalar_);
+  }
 }
 
-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);
+// Helper functions
+void ScalarHelper::SetPipeInfo(const 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 uint32_t GetScalarFormat(LayerBufferFormat source) {
+void ScalarHelper::UpdateSrcRoi(const 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);
+}
+
+void ScalarHelper::SetScaleData(const scalar::PipeInfo &pipe, ScaleData *scale_data) {
+  scalar::Scale *scale = pipe.scale_data;
+  scale_data->src_width = pipe.src_width;
+  scale_data->src_height = pipe.src_height;
+  scale_data->enable_pixel_ext = scale->enable_pxl_ext;
+
+  for (int i = 0; i < 4; i++) {
+    HWPlane &plane = scale_data->plane[i];
+    plane.init_phase_x = scale->init_phase_x[i];
+    plane.phase_step_x = scale->phase_step_x[i];
+    plane.init_phase_y = scale->init_phase_y[i];
+    plane.phase_step_y = scale->phase_step_y[i];
+
+    plane.left.extension = scale->left.extension[i];
+    plane.left.overfetch = scale->left.overfetch[i];
+    plane.left.repeat = scale->left.repeat[i];
+
+    plane.top.extension = scale->top.extension[i];
+    plane.top.overfetch = scale->top.overfetch[i];
+    plane.top.repeat = scale->top.repeat[i];
+
+    plane.right.extension = scale->right.extension[i];
+    plane.right.overfetch = scale->right.overfetch[i];
+    plane.right.repeat = scale->right.repeat[i];
+
+    plane.bottom.extension = scale->bottom.extension[i];
+    plane.bottom.overfetch = scale->bottom.overfetch[i];
+    plane.bottom.repeat = scale->bottom.repeat[i];
+
+    plane.roi_width = scale->roi_width[i];
+  }
+}
+
+uint32_t ScalarHelper::GetScalarFormat(LayerBufferFormat source) {
   uint32_t format = scalar::UNKNOWN_FORMAT;
 
   switch (source) {
@@ -101,48 +153,26 @@
   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_));
+DisplayError ScalarHelper::ConfigureScale(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]];
     uint32_t width = layer.input_buffer->width;
+    uint32_t height = layer.input_buffer->height;
     LayerBufferFormat format = layer.input_buffer->format;
-    HWPipeInfo* left_pipe = &hw_layers->config[i].left_pipe;
-    HWPipeInfo* right_pipe = &hw_layers->config[i].right_pipe;
+    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;
 
+    // Reset scale data
+    memset(&left_pipe.scale_data, 0, sizeof(ScaleData));
+    memset(&right_pipe.scale_data, 0, sizeof(ScaleData));
+
     // Prepare data structure for lib scalar
     uint32_t flags = 0;
     struct scalar::LayerInfo layer_info;
+    struct scalar::Scale left_scale, right_scale;
 
     if (layer.transform.rotation == 90.0f) {
       // Flips will be taken care by rotator, if layer requires 90 rotation
@@ -153,18 +183,20 @@
     }
 
     for (uint32_t count = 0; count < 2; count++) {
-      HWPipeInfo* hw_pipe = (count == 0) ? left_pipe : right_pipe;
+      const HWPipeInfo &hw_pipe = (count == 0) ? left_pipe : right_pipe;
       HWRotateInfo* hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
       scalar::PipeInfo* pipe = (count == 0) ? &layer_info.left_pipe : &layer_info.right_pipe;
 
       if (hw_rotate_info->valid) {
         width = UINT32(hw_rotate_info->dst_roi.right - hw_rotate_info->dst_roi.left);
+        height = UINT32(hw_rotate_info->dst_roi.bottom - hw_rotate_info->dst_roi.top);
         format = hw_rotator_session->output_buffer.format;
       }
 
       pipe->flags = flags;
-      pipe->scale_data = GetScaleRef(i, !count);
-      pipe->scale_data->src_width = width;
+      pipe->scale_data = (count == 0) ? &left_scale : &right_scale;
+      pipe->src_width = width;
+      pipe->src_height = height;
       SetPipeInfo(hw_pipe, pipe);
     }
     layer_info.src_format = GetScalarFormat(format);
@@ -184,57 +216,52 @@
       layer_info.right_pipe.dst_rect.w, layer_info.right_pipe.dst_rect.h);
 
     // Configure scale data structure
-    if (ScalarConfigureScale(&layer_info) < 0) {
+    if (configure_scale_(&layer_info) < 0) {
       DLOGE("Scalar library failed to configure scale data!");
-      return false;
+      return kErrorParameters;
     }
 
-    // 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);
+    // Set ScaleData and update SrcRoi in HWPipeInfo
+    if (left_scale.enable_pxl_ext) {
+      SetScaleData(layer_info.left_pipe, &left_pipe.scale_data);
+      UpdateSrcRoi(layer_info.left_pipe, &left_pipe);
+    }
+    if (right_scale.enable_pxl_ext) {
+      SetScaleData(layer_info.right_pipe, &right_pipe.scale_data);
+      UpdateSrcRoi(layer_info.right_pipe, &right_pipe);
+    }
   }
-  return true;
+
+  return kErrorNone;
 }
-
-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
+
+DisplayError Scalar::CreateScalar(Scalar **scalar) {
+  Scalar *scalar_obj = NULL;
+
+#ifdef USES_SCALAR
+  scalar_obj = new ScalarHelper();
+  if (scalar_obj) {
+    if (scalar_obj->Init() == kErrorNone) {
+      goto OnSuccess;
+    } else {
+      delete scalar_obj;
+    }
+  }
+#endif
+
+  scalar_obj = new Scalar();
+  if (!scalar_obj) {
+    return kErrorMemory;
+  }
+
+OnSuccess:
+  *scalar = scalar_obj;
+  return kErrorNone;
+}
+
+void Scalar::Destroy(Scalar *scalar) {
+  scalar->Deinit();
+}
+
+}  // namespace sde
diff --git a/displayengine/libs/core/scalar_helper.h b/displayengine/libs/core/scalar_helper.h
index a54cb0c..35217c5 100755
--- a/displayengine/libs/core/scalar_helper.h
+++ b/displayengine/libs/core/scalar_helper.h
@@ -25,43 +25,47 @@
 #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>
+#ifdef USES_SCALAR
 #include <scalar.h>
-
-#define SCALAR_LIBRARY_NAME "libscalar.so"
+#endif
 
 namespace sde {
 
-class ScalarHelper {
-
+class Scalar {
  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();
+  static DisplayError CreateScalar(Scalar **scalar);
+  static void Destroy(Scalar *scalar);
+  virtual ~Scalar() { }
+  virtual DisplayError ConfigureScale(HWLayers *hw_layers) { return kErrorNone; }
+
+ protected:
+  virtual DisplayError Init() { return kErrorNone; }
+  virtual void Deinit() { }
+};
+
+#ifdef USES_SCALAR
+class ScalarHelper : public Scalar {
+ public:
+  ScalarHelper();
+  virtual DisplayError ConfigureScale(HWLayers *hw_layers);
+
+ protected:
+  virtual DisplayError Init();
+  virtual void Deinit();
 
  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
+  const char *scalar_library_name_;
+  const char *configure_scale_api_;
+  void* lib_scalar_;
+  int (*configure_scale_)(scalar::LayerInfo *layer);
+  void SetPipeInfo(const HWPipeInfo &hw_pipe, scalar::PipeInfo *pipe);
+  void UpdateSrcRoi(const scalar::PipeInfo &pipe, HWPipeInfo *hw_pipe);
+  void SetScaleData(const scalar::PipeInfo &pipe, ScaleData *scale_data);
+  uint32_t GetScalarFormat(LayerBufferFormat source);
 };
+#endif
 
 }  // namespace sde
 
-#endif
 #endif  // __SCALAR_HELPER_H__
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 8a73d3c..724b720 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -33,6 +33,7 @@
 #include <utils/constants.h>
 #include <qdMetaData.h>
 #include <sync/sync.h>
+#include <cutils/properties.h>
 
 #include "hwc_display.h"
 #include "hwc_debugger.h"
@@ -45,7 +46,7 @@
                        int id)
   : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL),
     flush_(false), output_buffer_(NULL), dump_frame_count_(0), dump_frame_index_(0),
-    dump_input_layers_(false) {
+    dump_input_layers_(false), swap_interval_zero_(false) {
 }
 
 int HWCDisplay::Init() {
@@ -56,6 +57,13 @@
     return -EINVAL;
   }
 
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("debug.egl.swapinterval", property, "1") > 0) {
+    if (atoi(property) == 0) {
+      swap_interval_zero_ = true;
+    }
+  }
+
   return 0;
 }
 
@@ -452,6 +460,11 @@
         layer_buffer->planes[0].stride = pvt_handle->width;
       }
 
+      // if swapinterval property is set to 0 then close and reset the acquireFd
+      if (swap_interval_zero_ && hwc_layer.acquireFenceFd >= 0) {
+        close(hwc_layer.acquireFenceFd);
+        hwc_layer.acquireFenceFd = -1;
+      }
       layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
     }
 
@@ -485,6 +498,14 @@
     LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
 
     if (!flush_) {
+      // if swapinterval property is set to 0 then do not update f/w release fences with driver
+      // values
+      if (swap_interval_zero_) {
+        hwc_layer.releaseFenceFd = -1;
+        close(layer_buffer->release_fence_fd);
+        layer_buffer->release_fence_fd = -1;
+      }
+
       if (layer.composition != kCompositionGPU) {
         hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
       }
@@ -509,6 +530,11 @@
   if (!flush_) {
     layer_stack_cache_.animating = layer_stack_.flags.animating;
 
+    // if swapinterval property is set to 0 then close and reset the list retire fence
+    if (swap_interval_zero_) {
+      close(layer_stack_.retire_fence_fd);
+      layer_stack_.retire_fence_fd = -1;
+    }
     content_list->retireFenceFd = layer_stack_.retire_fence_fd;
 
     if (dump_frame_count_) {
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 7ef8187..d14699f 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -119,6 +119,7 @@
   uint32_t dump_frame_index_;
   bool dump_input_layers_;
   uint32_t last_power_mode_;
+  bool swap_interval_zero_;
 };
 
 }  // namespace sde
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 093b950..c51efba 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -281,14 +281,15 @@
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     const int dpy = HWC_DISPLAY_PRIMARY;
     bool fbComp = false;
-
+    static int compStart = false;
     if (!ctx->mBootAnimCompleted)
         processBootAnimCompleted(ctx);
     if (LIKELY(list && (list->numHwLayers > 1 ||
-                    ctx->mMDP.version < qdutils::MDP_V4_0)) &&
+                    (ctx->mMDP.version < qdutils::MDP_V4_0 && compStart))) &&
         ctx->dpyAttr[dpy].connected && (ctx->dpyAttr[dpy].isActive ||
              ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
             && !ctx->dpyAttr[dpy].isPause) {
+        compStart = true;
 
         // When HDMI is primary we should rely on the first valid
         // draw call in order to activate the display