hwc: Add BWC policy manager
Add a BWC policy manager that decides if BWC needs to be disabled on
certain conditions.
These conditions are statically determined. BWC might get used and
still fail (or cause failure of subsequent pipe requests) if SMP
blocks are not sufficient.
Change-Id: I805738911a8da7dfc6232c133c74ef844c3af5b1
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index b33b744..14b733a 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -728,12 +728,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);
- }
}
}
@@ -911,6 +905,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__);
@@ -1077,4 +1072,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 40bf352..4e3eecb 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 3e75d4e..2abdc19 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