Merge "hwc: Add BWC policy manager"
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index aa68467..b0ea0fc 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -733,12 +733,6 @@
         if(transform & HWC_TRANSFORM_ROT_90) {
             ovutils::setMdpFlags(mdpFlags,
                     ovutils::OV_MDP_SOURCE_ROTATED_90);
-            // enable bandwidth compression only if src width < 2048
-            if(qdutils::MDPVersion::getInstance().supportsBWC() &&
-                hnd->width < qdutils::MAX_DISPLAY_DIM) {
-                ovutils::setMdpFlags(mdpFlags,
-                                 ovutils::OV_MDSS_MDP_BWC_EN);
-            }
         }
     }
 
@@ -920,6 +914,7 @@
             ((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
         *rot = ctx->mRotMgr->getNext();
         if(*rot == NULL) return -1;
+        BwcPM::setBwc(ctx, crop, dst, transform, mdpFlags);
         //Configure rotator for pre-rotation
         if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
@@ -1087,4 +1082,43 @@
     return true;
 }
 
+
+void BwcPM::setBwc(hwc_context_t *ctx, const hwc_rect_t& crop,
+            const hwc_rect_t& dst, const int& transform,
+            ovutils::eMdpFlags& mdpFlags) {
+    //Target doesnt support Bwc
+    if(!qdutils::MDPVersion::getInstance().supportsBWC()) {
+        return;
+    }
+    //src width > MAX mixer supported dim
+    if((crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
+        return;
+    }
+    //External connected
+    if(ctx->mExtDisplay->isExternalConnected()) {
+        return;
+    }
+    //Decimation necessary, cannot use BWC. H/W requirement.
+    if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
+        int src_w = crop.right - crop.left;
+        int src_h = crop.bottom - crop.top;
+        int dst_w = dst.right - dst.left;
+        int dst_h = dst.bottom - dst.top;
+        if(transform & HAL_TRANSFORM_ROT_90) {
+            swap(src_w, src_h);
+        }
+        float horDscale = 0.0f;
+        float verDscale = 0.0f;
+        ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horDscale,
+                verDscale);
+        if(horDscale || verDscale) return;
+    }
+    //Property
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.disable.bwc", value, "0");
+     if(atoi(value)) return;
+
+    ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDSS_MDP_BWC_EN);
+}
+
 };//namespace qhwc
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index fb5e871..729a649 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -109,6 +109,12 @@
     bool fakevsync;
 };
 
+struct BwcPM {
+    static void setBwc(hwc_context_t *ctx, const hwc_rect_t& crop,
+            const hwc_rect_t& dst, const int& transform,
+            ovutils::eMdpFlags& mdpFlags);
+};
+
 // LayerProp::flag values
 enum {
     HWC_MDPCOMP = 0x00000001,
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 0de6276..71e7e5b 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -144,19 +144,11 @@
             minHorDeci = 2;
         }
 
-        float horDscale = ceilf((float)mOVInfo.src_rect.w /
-                (float)mOVInfo.dst_rect.w);
-        float verDscale = ceilf((float)mOVInfo.src_rect.h /
-                (float)mOVInfo.dst_rect.h);
+        float horDscale = 0.0f;
+        float verDscale = 0.0f;
 
-        //Next power of 2, if not already
-        horDscale = powf(2.0f, ceilf(log2f(horDscale)));
-        verDscale = powf(2.0f, ceilf(log2f(verDscale)));
-
-        //Since MDP can do 1/4 dscale and has better quality, split the task
-        //between decimator and MDP downscale
-        horDscale /= 4.0f;
-        verDscale /= 4.0f;
+        utils::getDecimationFactor(mOVInfo.src_rect.w, mOVInfo.src_rect.h,
+                mOVInfo.dst_rect.w, mOVInfo.dst_rect.h, horDscale, verDscale);
 
         if(horDscale < minHorDeci)
             horDscale = minHorDeci;
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index 4b81ed3..9bfa34e 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -244,6 +244,27 @@
     return dscale_factor;
 }
 
+//Since this is unavailable on Android, defining it in terms of base 10
+static inline float log2f(const float& x) {
+    return log(x) / log(2);
+}
+
+void getDecimationFactor(const int& src_w, const int& src_h,
+        const int& dst_w, const int& dst_h, float& horDscale,
+        float& verDscale) {
+    horDscale = ceilf((float)src_w / (float)dst_w);
+    verDscale = ceilf((float)src_h / (float)dst_h);
+
+    //Next power of 2, if not already
+    horDscale = powf(2.0f, ceilf(log2f(horDscale)));
+    verDscale = powf(2.0f, ceilf(log2f(verDscale)));
+
+    //Since MDP can do 1/4 dscale and has better quality, split the task
+    //between decimator and MDP downscale
+    horDscale /= 4.0f;
+    verDscale /= 4.0f;
+}
+
 static inline int compute(const uint32_t& x, const uint32_t& y,
         const uint32_t& z) {
     return x - ( y + z );
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index 3fa0979..4bb2151 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -393,6 +393,9 @@
 int getHALFormat(int mdpFormat);
 int getDownscaleFactor(const int& src_w, const int& src_h,
         const int& dst_w, const int& dst_h);
+void getDecimationFactor(const int& src_w, const int& src_h,
+        const int& dst_w, const int& dst_h, float& horDscale,
+        float& verDscale);
 
 /* flip is upside down and such. V, H flip
  * rotation is 90, 180 etc