Merge "sde: Add decimation support for downscaling."
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index f6c84c2..38320a4 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -545,7 +545,11 @@
       mdp_layer.alpha = layer.plane_alpha;
       mdp_layer.z_order = static_cast<uint16_t>(i);
       mdp_layer.transp_mask = 0xffffffff;
+      mdp_layer.horz_deci = pipe.horizontal_decimation;
+      mdp_layer.vert_deci = pipe.vertical_decimation;
+
       SetBlending(layer.blending, &mdp_layer.blend_op);
+
       SetRect(pipe.src_roi, &mdp_layer.src_rect);
       SetRect(pipe.dst_roi, &mdp_layer.dst_rect);
 
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index c7c9aa5..c8611f9 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -110,9 +110,10 @@
   int pipe_id;
   LayerRect src_roi;
   LayerRect dst_roi;
-  uint8_t decimation;
+  uint8_t horizontal_decimation;
+  uint8_t vertical_decimation;
 
-  HWPipeInfo() : pipe_id(0), decimation(1) { }
+  HWPipeInfo() : pipe_id(0), horizontal_decimation(0), vertical_decimation(0) { }
 
   inline void Reset() { *this = HWPipeInfo(); }
 };
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index a915b7d..1fc1598 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -426,22 +426,41 @@
   }
 }
 
-void ResManager::SetDecimationFactor(HWPipeInfo *pipe) {
+DisplayError ResManager::SetDecimationFactor(HWPipeInfo *pipe) {
   float max_down_scale = FLOAT(hw_res_info_.max_scale_down);
   float src_h = pipe->src_roi.bottom - pipe->src_roi.top;
   float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
-  float down_scale = src_h / dst_h;
-  pipe->decimation = 1;
+  float down_scale_h = src_h / dst_h;
 
-  if (!hw_res_info_.has_decimation || (down_scale <= max_down_scale))
-    return;
+  float src_w = pipe->src_roi.right - pipe->src_roi.left;
+  float dst_w = pipe->dst_roi.right - pipe->dst_roi.left;
+  float down_scale_w = src_w / dst_w;
+
+
+  pipe->horizontal_decimation = 0;
+  pipe->vertical_decimation = 0;
+
+  // TODO(user): Need to check for the maximum downscale limit for decimation and return error
+  if (!hw_res_info_.has_decimation && ((down_scale_w > max_down_scale) ||
+      (down_scale_h > max_down_scale))) {
+    DLOGV("Downscaling exceeds the maximum MDP downscale limit and decimation not enabled");
+    return kErrorNotSupported;
+  }
+
+  if ((down_scale_w <= max_down_scale) && (down_scale_h <= max_down_scale))
+    return kErrorNone;
 
   // Decimation is the remaining downscale factor after doing max SDE downscale.
   // In SDE, decimation is supported in powers of 2.
   // For ex: If a pipe needs downscale of 8 but max_down_scale is 4
   // So decimation = powf(2.0, ceilf(log2f(8) - log2f(4))) = powf(2.0, 1.0) = 2
-  float decimation_factor = ceilf(log2f(down_scale) - log2f(max_down_scale));
-  pipe->decimation = UINT8(powf(2.0f, decimation_factor));
+  pipe->horizontal_decimation = UINT8(ceilf(log2f(down_scale_w) - log2f(max_down_scale)));
+  pipe->vertical_decimation = UINT8(ceilf(log2f(down_scale_h) - log2f(max_down_scale)));
+
+  DLOGI_IF(kTagResources, "horizontal_decimation %d, vertical_decimation %d",
+           pipe->horizontal_decimation, pipe->vertical_decimation);
+
+  return kErrorNone;
 }
 
 void ResManager::SplitRect(bool flip_horizontal, const LayerRect &src_rect,
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 7b36563..12ef5bd 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -22,6 +22,7 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#include <math.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
 
@@ -286,7 +287,10 @@
       src_pipes_[left_index].reserved_hw_block = hw_block_id;
     }
 
-    SetDecimationFactor(pipe_info);
+    error = SetDecimationFactor(pipe_info);
+    if (error != kErrorNone) {
+      goto CleanupOnError;
+    }
 
     pipe_info =  &layer_config.right_pipe;
     if (pipe_info->pipe_id == 0) {
@@ -318,7 +322,10 @@
     src_pipes_[left_index].reserved_hw_block = hw_block_id;
     src_pipes_[left_index].at_right = false;
     layer_config.left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
-    SetDecimationFactor(pipe_info);
+    error = SetDecimationFactor(pipe_info);
+    if (error != kErrorNone) {
+      goto CleanupOnError;
+    }
 
     DLOGV_IF(kTagResources, "Pipe acquired, layer index = %d, left_pipe = %x, right_pipe = %x",
             i, layer_config.left_pipe.pipe_id,  pipe_info->pipe_id);
@@ -418,7 +425,8 @@
   float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
 
   // Adjust src_h with pipe decimation
-  src_h /= FLOAT(pipe->decimation);
+  float decimation = powf(2.0f, pipe->vertical_decimation);
+  src_h /= decimation;
 
   float bw = src_w * src_h * bpp * display_attributes.fps;
 
@@ -440,7 +448,9 @@
   float dst_w = pipe->dst_roi.right - pipe->dst_roi.left;
 
   // Adjust src_h with pipe decimation
-  src_h /= FLOAT(pipe->decimation);
+  float decimation = powf(2.0f, pipe->vertical_decimation);
+  src_h /= decimation;
+
 
   // SDE Clock requirement in MHz
   float clk = (dst_w * v_total * fps) / 1000000.0f;
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 28bae1c..cf0a55f 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -166,7 +166,7 @@
   float GetPipeBw(DisplayResourceContext *display_ctx, HWPipeInfo *pipe, float bpp);
   float GetClockForPipe(DisplayResourceContext *display_ctx, HWPipeInfo *pipe);
   float GetOverlapBw(HWLayers *hw_layers, float *pipe_bw, bool left_mixer);
-  void SetDecimationFactor(HWPipeInfo *pipe);
+  DisplayError SetDecimationFactor(HWPipeInfo *pipe);
   float GetBpp(LayerBufferFormat format);
   void SplitRect(bool flip_horizontal, const LayerRect &src_rect, const LayerRect &dst_rect,
                  LayerRect *src_left, LayerRect *dst_left, LayerRect *src_right,