Merge "hwc: Avoid MDP comp for RGB downscaled layer"
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 5bd7931..e2c4677 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -55,6 +55,7 @@
 int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
 int (*MDPComp::sPerfLockRelease)(int value) = NULL;
 int MDPComp::sPerfHintWindow = -1;
+float MDPComp::sDownscaleThreshold = 1.0;
 
 enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
 
@@ -212,6 +213,10 @@
         }
     }
 
+    if(property_get("persist.hwc.downscale_threshold", property, "1.0") > 0) {
+        sDownscaleThreshold = (float)atof(property);
+    }
+
     return true;
 }
 
@@ -430,6 +435,24 @@
         //More conditions here, sRGB+Blend etc
         return false;
     }
+
+    //In targets with fewer pipes, frequent composition switch between MDP/GPU
+    //can happen for a layer due to lack of pipes. When this switch happens
+    //continuously for RGB downscaled layer with downscale greater than
+    //threshold, it appears as flicker as output
+    //of MDP and GPU are different as they use different filters for downscale.
+    //To avoid this flicker, punt RGB downscaled layer with downscale greater
+    //than threshold value to GPU always.
+    if((sDownscaleThreshold > 1.0)) {
+        if(((not isYuvBuffer(hnd))
+                and (not isDownscaleWithinThreshold(layer,
+                        sDownscaleThreshold)))) {
+            ALOGD_IF(isDebug(), "%s: required downscale is greater than \
+                    threshold %f", __FUNCTION__, sDownscaleThreshold);
+            return false;
+        }
+    }
+
     return true;
 }
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index db68e82..5c43aa7 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -283,6 +283,7 @@
     static int (*sPerfLockAcquire)(int, int, int*, int);
     static int (*sPerfLockRelease)(int value);
     static int sPerfHintWindow;
+    static float sDownscaleThreshold;
 
 };
 
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index aeda428..79235ff 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -972,6 +972,27 @@
 
     return false;
 }
+
+bool isDownscaleWithinThreshold(hwc_layer_1_t const* layer, float threshold) {
+    hwc_rect_t displayFrame  = layer->displayFrame;
+    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+    int dst_w, dst_h, src_w, src_h;
+    float downscale = 1.0;
+    dst_w = displayFrame.right - displayFrame.left;
+    dst_h = displayFrame.bottom - displayFrame.top;
+    src_w = sourceCrop.right - sourceCrop.left;
+    src_h = sourceCrop.bottom - sourceCrop.top;
+    if(dst_w && dst_h) {
+        float w_scale = ((float)src_w / (float)dst_w);
+        float h_scale = ((float)src_h / (float)dst_h);
+
+        if((w_scale > threshold) or (h_scale > threshold))
+            return false;
+    }
+
+    return true;
+}
+
 bool needsScaling(hwc_layer_1_t const* layer) {
     int dst_w, dst_h, src_w, src_h;
     hwc_rect_t displayFrame  = layer->displayFrame;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index da0182b..4849baf 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -309,6 +309,7 @@
 bool isAlphaScaled(hwc_layer_1_t const* layer);
 bool needsScaling(hwc_layer_1_t const* layer);
 bool isDownscaleRequired(hwc_layer_1_t const* layer);
+bool isDownscaleWithinThreshold(hwc_layer_1_t const* layer, float threshold);
 bool needsScalingWithSplit(hwc_context_t* ctx, hwc_layer_1_t const* layer,
                            const int& dpy);
 void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,