Merge "hwc: Handle worm hole region for one line"
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
index 0a37c79..96ec20f 100644
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -124,7 +124,11 @@
   uint64_t secure_present : 1;    //!< This flag will be set to true, if the current layer stack
                                   //!< contains secure layers.
 
-  LayerStackFlags() : geometry_changed(0), skip_present(0), video_present(0), secure_present(0) { }
+  uint64_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) { }
 };
 
 /*! @brief This structure defines a rectanglular area inside a display layer.
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index 04a5f77..6f98b07 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -53,6 +53,24 @@
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
 
+template <class T>
+inline void Swap(T &a, T &b) {
+  T c(a);
+  a = b;
+  b = c;
+}
+
+// factor value should be in powers of 2(eg: 1, 2, 4, 8)
+template <class T1, class T2>
+inline T1 FloorToMultipleOf(const T1 &value, const T2 &factor) {
+  return (T1)(value & (~(factor - 1)));
+}
+
+template <class T1, class T2>
+inline T1 CeilToMultipleOf(const T1 &value, const T2 &factor) {
+  return (T1)((value + (factor - 1)) & (~(factor - 1)));
+}
+
 namespace sde {
 
   const int kThreadPriorityUrgent = -9;
diff --git a/displayengine/include/utils/rect.h b/displayengine/include/utils/rect.h
new file mode 100644
index 0000000..f009cfd
--- /dev/null
+++ b/displayengine/include/utils/rect.h
@@ -0,0 +1,48 @@
+/*
+* 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 __RECT_H__
+#define __RECT_H__
+
+#include <stdint.h>
+#include <core/sde_types.h>
+#include <core/layer_stack.h>
+#include <utils/debug.h>
+
+namespace sde {
+
+  bool IsValidRect(const LayerRect &rect);
+  LayerRect GetIntersection(const LayerRect &rect1, const LayerRect &rect2);
+  void LogRect(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
+  void NormalizeRect(const uint32_t &factor, LayerRect *rect);
+
+}  // namespace sde
+
+#endif  // __RECT_H__
+
diff --git a/displayengine/libs/core/Android.mk b/displayengine/libs/core/Android.mk
index 1623c13..56167e1 100644
--- a/displayengine/libs/core/Android.mk
+++ b/displayengine/libs/core/Android.mk
@@ -4,7 +4,8 @@
 LOCAL_MODULE                  := libsde
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := hardware/qcom/display/displayengine/include/ \
-                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
+                                 $(TARGET_OUT_HEADERS)/scalar/inc
 LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
                                  -Wconversion -Wall -Werror \
                                  -DLOG_TAG=\"SDE\"
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 5d1f725..4a361da 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -722,6 +722,14 @@
           }
         }
 
+        if (pipe_info->scale_data.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);
+        }
+
+        // Send scale data to MDP driver
+        mdp_layer.scale = hw_display->GetScaleRef(mdp_layer_count);
         mdp_layer_count++;
 
         DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
@@ -735,6 +743,19 @@
                  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++) {
+          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],
+                 mdp_layer.scale->num_ext_pxls_left[j], mdp_layer.scale->num_ext_pxls_top[j],
+                 mdp_layer.scale->num_ext_pxls_right[j], mdp_layer.scale->num_ext_pxls_btm[j]);
+          DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d]  Repeat=[%d %d %d %d]  roi_width = %d",
+                 mdp_layer.scale->left_ftch[j], mdp_layer.scale->top_ftch[j],
+                 mdp_layer.scale->right_ftch[j], mdp_layer.scale->btm_ftch[j],
+                 mdp_layer.scale->left_rpt[j], mdp_layer.scale->top_rpt[j],
+                 mdp_layer.scale->right_rpt[j], mdp_layer.scale->btm_rpt[j],
+                 mdp_layer.scale->roi_w[j]);
+        }
         DLOGV_IF(kTagDriverConfig, "*************************************************************");
       }
     }
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index 6df705d..5c01e5f 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -67,6 +67,7 @@
   struct HWDisplay {
     mdp_layer_commit mdp_disp_commit;
     mdp_input_layer mdp_in_layers[kMaxSDELayers * 2];   // split panel (left + right)
+    mdp_scale_data scale_data[kMaxSDELayers * 2];
     mdp_output_layer mdp_out_layer;
 
     HWDisplay() { Reset(); }
@@ -75,6 +76,7 @@
       memset(&mdp_disp_commit, 0, sizeof(mdp_disp_commit));
       memset(&mdp_in_layers, 0, sizeof(mdp_in_layers));
       memset(&mdp_out_layer, 0, sizeof(mdp_out_layer));
+      memset(&scale_data, 0, sizeof(scale_data));
 
       for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
         mdp_in_layers[i].buffer.fence = -1;
@@ -85,6 +87,37 @@
       mdp_disp_commit.commit_v1.output_layer = &mdp_out_layer;
       mdp_disp_commit.commit_v1.release_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];
+      }
+    }
   };
 
   struct HWRotator {
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 1217b95..084768e 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -30,6 +30,7 @@
 #include <utils/constants.h>
 #include <core/buffer_allocator.h>
 #include <core/buffer_sync_handler.h>
+#include <scalar.h>
 
 namespace sde {
 
@@ -128,6 +129,7 @@
   LayerRect dst_roi;
   uint8_t horizontal_decimation;
   uint8_t vertical_decimation;
+  scalar::Scale scale_data;
   bool valid;
 
   HWPipeInfo() : pipe_id(0), horizontal_decimation(0), vertical_decimation(0), valid(false) { }
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index cf2a5c7..d3c2d26 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -25,11 +25,15 @@
 #include <math.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
+#include <utils/rect.h>
 
 #include "res_manager.h"
 
 #define __CLASS__ "ResManager"
 
+using scalar::PipeInfo;
+using scalar::LayerInfo;
+
 namespace sde {
 
 void ResManager::RotationConfig(const LayerTransform &transform, const float &scale_x,
@@ -179,8 +183,8 @@
     float rot_scale_x = 1.0f, rot_scale_y = 1.0f;
     if (!IsValidDimension(layer.src_rect, layer.dst_rect)) {
       DLOGV_IF(kTagResources, "Input is invalid");
-      LogRectVerbose("input layer src_rect", layer.src_rect);
-      LogRectVerbose("input layer dst_rect", layer.dst_rect);
+      LogRect(kTagResources, "input layer src_rect", layer.src_rect);
+      LogRect(kTagResources, "input layer dst_rect", layer.dst_rect);
       return kErrorNotSupported;
     }
 
@@ -239,21 +243,21 @@
 
     DLOGV_IF(kTagResources, "layer = %d, left pipe_id = %x",
              i, layer_config->left_pipe.pipe_id);
-    LogRectVerbose("input layer src_rect", layer.src_rect);
-    LogRectVerbose("input layer dst_rect", layer.dst_rect);
+    LogRect(kTagResources, "input layer src_rect", layer.src_rect);
+    LogRect(kTagResources, "input layer dst_rect", layer.dst_rect);
     for (uint32_t k = 0; k < layer_config->num_rotate; k++) {
       DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f, scale_y = %.2f",
                k, rot_scale_x, rot_scale_y);
-      LogRectVerbose("rotate src", layer_config->rotates[k].src_roi);
-      LogRectVerbose("rotate dst", layer_config->rotates[k].dst_roi);
+      LogRect(kTagResources, "rotate src", layer_config->rotates[k].src_roi);
+      LogRect(kTagResources, "rotate dst", layer_config->rotates[k].dst_roi);
     }
-    LogRectVerbose("cropped src_rect", src_rect);
-    LogRectVerbose("cropped dst_rect", dst_rect);
-    LogRectVerbose("left pipe src", layer_config->left_pipe.src_roi);
-    LogRectVerbose("left pipe dst", layer_config->left_pipe.dst_roi);
+    LogRect(kTagResources, "cropped src_rect", src_rect);
+    LogRect(kTagResources, "cropped dst_rect", dst_rect);
+    LogRect(kTagResources, "left pipe src", layer_config->left_pipe.src_roi);
+    LogRect(kTagResources, "left pipe dst", layer_config->left_pipe.dst_roi);
     if (hw_layers->config[i].right_pipe.pipe_id) {
-      LogRectVerbose("right pipe src", layer_config->right_pipe.src_roi);
-      LogRectVerbose("right pipe dst", layer_config->right_pipe.dst_roi);
+      LogRect(kTagResources, "right pipe src", layer_config->right_pipe.src_roi);
+      LogRect(kTagResources, "right pipe dst", layer_config->right_pipe.dst_roi);
     }
   }
 
@@ -529,21 +533,123 @@
   }
 }
 
-void ResManager::LogRectVerbose(const char *prefix, const LayerRect &roi) {
-  DLOGV_IF(kTagResources, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
-           prefix, roi.left, roi.top, roi.right, roi.bottom);
+// 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;
 }
 
-void ResManager::NormalizeRect(const uint32_t &factor, LayerRect *rect) {
-  uint32_t left = UINT32(ceilf(rect->left));
-  uint32_t top = UINT32(ceilf(rect->top));
-  uint32_t right = UINT32(floorf(rect->right));
-  uint32_t bottom = UINT32(floorf(rect->bottom));
+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);
+}
 
-  rect->left = FLOAT(CeilToMultipleOf(left, factor));
-  rect->top = FLOAT(CeilToMultipleOf(top, factor));
-  rect->right = FLOAT(FloorToMultipleOf(right, factor));
-  rect->bottom = FLOAT(FloorToMultipleOf(bottom, factor));
+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;
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 16fc8b4..fb8f2eb 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -25,10 +25,12 @@
 #include <math.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
+#include <dlfcn.h>
 
 #include "res_manager.h"
 
 #define __CLASS__ "ResManager"
+#define SCALAR_LIBRARY_NAME "libscalar.so"
 
 namespace sde {
 
@@ -112,10 +114,23 @@
   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);
+  }
+
   return kErrorNone;
 }
 
 DisplayError ResManager::Deinit() {
+  if (lib_scalar_handle_) {
+    dlclose(lib_scalar_handle_);
+    lib_scalar_handle_ = NULL;
+  }
   return kErrorNone;
 }
 
@@ -353,17 +368,24 @@
             i, layer_config.left_pipe.pipe_id,  pipe_info->pipe_id);
   }
 
-  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;
   }
 
+  if (lib_scalar_handle_ && ScalarConfigureScale) {
+    if (!ConfigureScaling(hw_layers)) {
+      DLOGV_IF(kTagResources, "Scale data configuration has failed!");
+      goto CleanupOnError;
+    }
+  }
+
+  if (!CheckBandwidth(display_resource_ctx, hw_layers)) {
+    DLOGV_IF(kTagResources, "Bandwidth check failed!");
+    goto CleanupOnError;
+  }
+
   return kErrorNone;
 
 CleanupOnError:
@@ -1065,6 +1087,8 @@
   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 926b2b7..c80dc2c 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -187,7 +187,6 @@
   bool IsYuvFormat(LayerBufferFormat format) { return (format >= kFormatYCbCr420Planar); }
   bool IsRotationNeeded(float rotation)
          { return (UINT32(rotation) == 90 || UINT32(rotation) == 270); }
-  void LogRectVerbose(const char *prefix, const LayerRect &roi);
   void RotationConfig(const LayerTransform &transform, const float &scale_x,
                       const float &scale_y, LayerRect *src_rect,
                       struct HWLayerConfig *layer_config, uint32_t *rotate_count);
@@ -195,28 +194,10 @@
                               const uint32_t roate_cnt);
   void AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_cnt);
   void ClearRotator(DisplayResourceContext *display_resource_ctx);
-  void NormalizeRect(const uint32_t &factor, LayerRect *rect);
   DisplayError AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers);
   void SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
                               LayerBufferFormat *output_format);
-
-  template <class T>
-  inline void Swap(T &a, T &b) {
-    T c(a);
-    a = b;
-    b = c;
-  }
-
-  // factor value should be in powers of 2(eg: 1, 2, 4, 8)
-  template <class T1, class T2>
-  inline T1 FloorToMultipleOf(const T1 &value, const T2 &factor) {
-    return (T1)(value & (~(factor - 1)));
-  }
-
-  template <class T1, class T2>
-  inline T1 CeilToMultipleOf(const T1 &value, const T2 &factor) {
-    return (T1)((value + (factor - 1)) & (~(factor - 1)));
-  }
+  bool ConfigureScaling(HWLayers *hw_layers);
 
   Locker locker_;
   HWResourceInfo hw_res_info_;
@@ -235,6 +216,8 @@
   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);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 452bff1..dd1beac 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -361,6 +361,10 @@
     layer.flags.skip = ((hwc_layer.flags & HWC_SKIP_LAYER) > 0);
     layer.flags.updating = (layer_stack_cache_.layer_cache[i].handle != hwc_layer.handle);
 
+    if (hwc_layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
+      layer_stack_.flags.animating = true;
+    }
+
     if (layer.flags.skip) {
       layer_stack_.flags.skip_present = true;
     }
@@ -462,17 +466,31 @@
     Layer &layer = layer_stack_.layers[i];
     LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
 
-    if (!flush_ && (layer.composition == kCompositionSDE ||
-                         layer.composition == kCompositionGPUTarget)) {
-      hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
+    if (!flush_) {
+      if (layer.composition != kCompositionGPU) {
+        hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
+      }
+
+      // During animation on external/virtual display, Display Engine will use the cached
+      // framebuffer layer throughout animation and do not allow framework to do eglswapbuffer on
+      // framebuffer target. So graphics doesn't close the release fence fd of framebuffer target,
+      // Hence close the release fencefd of framebuffer target here.
+      if (layer.composition == kCompositionGPUTarget && layer_stack_cache_.animating) {
+        close(hwc_layer.releaseFenceFd);
+        hwc_layer.releaseFenceFd = -1;
+      }
     }
 
     if (hwc_layer.acquireFenceFd >= 0) {
       close(hwc_layer.acquireFenceFd);
+      hwc_layer.acquireFenceFd = -1;
     }
   }
 
+
   if (!flush_) {
+    layer_stack_cache_.animating = layer_stack_.flags.animating;
+
     content_list->retireFenceFd = layer_stack_.retire_fence_fd;
 
     if (dump_frame_count_) {
@@ -495,8 +513,8 @@
   // 2. Any layer is added/removed/layer properties changes in the current layer stack.
   // 3. Any layer handle is changed and it is marked for GPU composition
   // 4. Any layer's current composition is different from previous composition.
-  if ((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
-       layer_stack_.flags.geometry_changed) {
+  if (((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
+      layer_stack_.flags.geometry_changed) && !layer_stack_cache_.animating) {
     return true;
   }
 
@@ -513,7 +531,8 @@
       return true;
     }
 
-    if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle)) {
+    if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle) &&
+        !layer_stack_cache_.animating) {
       return true;
     }
   }
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 3934078..a574d6b 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -69,8 +69,9 @@
   struct LayerStackCache {
     LayerCache layer_cache[kMaxLayerCount];
     uint32_t layer_count;
+    bool animating;
 
-    LayerStackCache() : layer_count(0) { }
+    LayerStackCache() : layer_count(0), animating(false) { }
   };
 
   HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type, int id);
diff --git a/displayengine/libs/utils/Android.mk b/displayengine/libs/utils/Android.mk
index db97dd5..264c40a 100644
--- a/displayengine/libs/utils/Android.mk
+++ b/displayengine/libs/utils/Android.mk
@@ -8,6 +8,6 @@
                                  -Wconversion -Wall -Werror \
                                  -DLOG_TAG=\"SDE\"
 LOCAL_SHARED_LIBRARIES        := libcutils
-LOCAL_SRC_FILES               := debug_android.cpp
+LOCAL_SRC_FILES               := debug_android.cpp rect.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/utils/rect.cpp b/displayengine/libs/utils/rect.cpp
new file mode 100644
index 0000000..2725750
--- /dev/null
+++ b/displayengine/libs/utils/rect.cpp
@@ -0,0 +1,80 @@
+/*
+* 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.
+*/
+
+#include <math.h>
+#include <utils/rect.h>
+#include <utils/constants.h>
+
+#define __CLASS__ "RectUtils"
+
+namespace sde {
+
+bool IsValidRect(const LayerRect &rect) {
+  return ((rect.bottom > rect.top) && (rect.right > rect.left));
+}
+
+
+LayerRect GetIntersection(const LayerRect &rect1, const LayerRect &rect2) {
+  LayerRect res;
+
+  if (!IsValidRect(rect1) || !IsValidRect(rect2)) {
+    return LayerRect();
+  }
+
+  res.left = MAX(rect1.left, rect2.left);
+  res.top = MAX(rect1.top, rect2.top);
+  res.right = MIN(rect1.right, rect2.right);
+  res.bottom = MIN(rect1.bottom, rect2.bottom);
+
+  if (!IsValidRect(res)) {
+    return LayerRect();
+  }
+
+  return res;
+}
+
+void LogRect(DebugTag debug_tag, const char *prefix, const LayerRect &roi) {
+  DLOGV_IF(debug_tag, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
+           prefix, roi.left, roi.top, roi.right, roi.bottom);
+}
+
+void NormalizeRect(const uint32_t &factor, LayerRect *rect) {
+  uint32_t left = UINT32(ceilf(rect->left));
+  uint32_t top = UINT32(ceilf(rect->top));
+  uint32_t right = UINT32(floorf(rect->right));
+  uint32_t bottom = UINT32(floorf(rect->bottom));
+
+  rect->left = FLOAT(CeilToMultipleOf(left, factor));
+  rect->top = FLOAT(CeilToMultipleOf(top, factor));
+  rect->right = FLOAT(FloorToMultipleOf(right, factor));
+  rect->bottom = FLOAT(FloorToMultipleOf(bottom, factor));
+}
+
+}  // namespace sde
+
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 8b134ea..e9b9d9d 100755
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -91,7 +91,6 @@
                              GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
 
 #define INTERLACE_MASK 0x80
-#define S3D_FORMAT_MASK 0xFF000
 /*****************************************************************************/
 
 /* OEM specific HAL formats */
@@ -155,15 +154,11 @@
 
 /* possible formats for 3D content*/
 enum {
-    HAL_NO_3D                         = 0x0000,
-    HAL_3D_IN_SIDE_BY_SIDE_L_R        = 0x10000,
-    HAL_3D_IN_TOP_BOTTOM              = 0x20000,
-    HAL_3D_IN_INTERLEAVE              = 0x40000,
-    HAL_3D_IN_SIDE_BY_SIDE_R_L        = 0x80000,
-    HAL_3D_OUT_SIDE_BY_SIDE           = 0x1000,
-    HAL_3D_OUT_TOP_BOTTOM             = 0x2000,
-    HAL_3D_OUT_INTERLEAVE             = 0x4000,
-    HAL_3D_OUT_MONOSCOPIC             = 0x8000
+    HAL_NO_3D                      = 0x0,
+    HAL_3D_SIDE_BY_SIDE_L_R        = 0x1,
+    HAL_3D_SIDE_BY_SIDE_R_L        = 0x2,
+    HAL_3D_TOP_BOTTOM              = 0x4,
+    HAL_3D_IN_SIDE_BY_SIDE_L_R     = 0x10000, //unused legacy format
 };
 
 enum {
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 1891c46..65482d7 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution.
  *
@@ -948,16 +948,18 @@
        int tmp_w =  src_crop_width;
        int tmp_h =  src_crop_height;
 
-       if (dsdx > copybitsMaxScale || dtdy > copybitsMaxScale ){
+       if (dsdx > copybitsMaxScale)
          tmp_w = (int)((float)src_crop_width*copybitsMaxScale);
+       if (dtdy > copybitsMaxScale)
          tmp_h = (int)((float)src_crop_height*copybitsMaxScale);
-       }else if (dsdx < 1/copybitsMinScale ||dtdy < 1/copybitsMinScale ){
-         // ceil the tmp_w and tmp_h value to maintain proper ratio
-         // b/w src and dst (should not cross the desired scale limit
-         // due to float -> int )
+       // ceil the tmp_w and tmp_h value to maintain proper ratio
+       // b/w src and dst (should not cross the desired scale limit
+       // due to float -> int )
+       if (dsdx < 1/copybitsMinScale)
          tmp_w = (int)ceil((float)src_crop_width/copybitsMinScale);
+       if (dtdy < 1/copybitsMinScale)
          tmp_h = (int)ceil((float)src_crop_height/copybitsMinScale);
-       }
+
        ALOGD("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
 
        int usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 4f1b5e6..a97c59b 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -245,10 +245,10 @@
 
 inline hwc_rect_t integerizeSourceCrop(const hwc_frect_t& cropF) {
     hwc_rect_t cropI = {0,0,0,0};
-    cropI.left = int(ceilf(cropF.left));
-    cropI.top = int(ceilf(cropF.top));
-    cropI.right = int(floorf(cropF.right));
-    cropI.bottom = int(floorf(cropF.bottom));
+    cropI.left = int(floorf(cropF.left));
+    cropI.top = int(floorf(cropF.top));
+    cropI.right = int(ceilf(cropF.right));
+    cropI.bottom = int(ceilf(cropF.bottom));
     return cropI;
 }
 
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index 88109c9..aae0a47 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-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
@@ -93,6 +93,9 @@
         case MAP_SECURE_BUFFER:
             data->mapSecureBuffer = *((int32_t *)param);
             break;
+        case S3D_FORMAT:
+            data->s3dFormat = *((uint32_t *)param);
+            break;
         default:
             ALOGE("Unknown paramType %d", paramType);
             break;
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
index 32d788e..a1afa38 100644
--- a/libqdutils/qdMetaData.h
+++ b/libqdutils/qdMetaData.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-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
@@ -86,6 +86,9 @@
       * for clients to set, and GPU will to read and know when to map the
       * SECURE_BUFFER(ION) */
     int32_t mapSecureBuffer;
+    /* The supported formats are defined in gralloc_priv.h to
+     * support legacy code*/
+    uint32_t s3dFormat;
 };
 
 enum DispParamType {
@@ -100,6 +103,7 @@
     UPDATE_REFRESH_RATE = 0x0100,
     UPDATE_COLOR_SPACE = 0x0200,
     MAP_SECURE_BUFFER = 0x400,
+    S3D_FORMAT = 0x800,
 };
 
 struct private_handle_t;