overlay: Add support for decimation.
Add support for decimation on top of what MDP can downscale,
because decimation can have quality issues.
B-family MDP downscale of 1/4, plus decimation of 1/16 can let
us have a total downscale of 1/64.
Also decimate by 2 (min) if width is greater than what layer mixer
supports and is not handled by the client.
Change-Id: I3b7c4bf321c7561bd98206ad118f4ac1ee2879ae
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index b8e6976..9f91a99 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -21,6 +21,9 @@
#define DEBUG_FBUPDATE 0
#include <gralloc_priv.h>
#include "hwc_fbupdate.h"
+#include "mdp_version.h"
+
+using namespace qdutils;
namespace qhwc {
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index b81eb5e..6381f59 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -24,6 +24,7 @@
#include <overlayRotator.h>
using namespace overlay;
+using namespace qdutils;
using namespace overlay::utils;
namespace ovutils = overlay::utils;
@@ -405,12 +406,11 @@
return false;
}
- /* Workaround for downscales larger than 4x. Will be removed once decimator
- * block is enabled for MDSS*/
- if(ctx->mMDP.version == qdutils::MDSS_V5) {
+ if(!qdutils::MDPVersion::getInstance().supportsDecimation()) {
+ const uint32_t downscale =
+ qdutils::MDPVersion::getInstance().getMaxMDPDownscale();
hwc_rect_t crop = layer->sourceCrop;
hwc_rect_t dst = layer->displayFrame;
-
int cWidth = crop.right - crop.left;
int cHeight = crop.bottom - crop.top;
int dWidth = dst.right - dst.left;
@@ -420,7 +420,8 @@
swap(cWidth, cHeight);
}
- if((cWidth/dWidth) > 4 || (cHeight/dHeight) > 4)
+ if(cWidth > MAX_DISPLAY_DIM || (cWidth/dWidth) > downscale ||
+ (cHeight/dHeight) > downscale)
return false;
}
return true;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 001e3e8..d4f5d94 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -34,7 +34,6 @@
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
#define MAX_NUM_LAYERS 32 //includes fb layer
-#define MAX_DISPLAY_DIM 2048
// For support of virtual displays
#define HWC_DISPLAY_VIRTUAL (HWC_DISPLAY_EXTERNAL+1)
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 96cb56e..d70ab64 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#include <math.h>
#include <mdp_version.h>
#include "overlayUtils.h"
#include "overlayMdp.h"
@@ -22,10 +23,17 @@
#define HSIC_SETTINGS_DEBUG 0
+using namespace qdutils;
+
static inline bool isEqual(float f1, float f2) {
return ((int)(f1*100) == (int)(f2*100)) ? true : false;
}
+//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);
+}
+
namespace ovutils = overlay::utils;
namespace overlay {
@@ -130,14 +138,52 @@
}
void MdpCtrl::doDownscale() {
- mOVInfo.src_rect.x >>= mDownscale;
- mOVInfo.src_rect.y >>= mDownscale;
- mOVInfo.src_rect.w >>= mDownscale;
- mOVInfo.src_rect.h >>= mDownscale;
+ int mdpVersion = MDPVersion::getInstance().getMDPVersion();
+ if(mdpVersion < MDSS_V5) {
+ mOVInfo.src_rect.x >>= mDownscale;
+ mOVInfo.src_rect.y >>= mDownscale;
+ mOVInfo.src_rect.w >>= mDownscale;
+ mOVInfo.src_rect.h >>= mDownscale;
+ } else if(MDPVersion::getInstance().supportsDecimation()) {
+ //Decimation + MDP Downscale
+ mOVInfo.horz_deci = 0;
+ mOVInfo.vert_deci = 0;
+ int minHorDeci = 0;
+ if(mOVInfo.src_rect.w > 2048) {
+ //If the client sends us something > what a layer mixer supports
+ //then it means it doesn't want to use split-pipe but wants us to
+ //decimate. A minimum decimation of 2 will ensure that the width is
+ //always within layer mixer limits.
+ 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);
+
+ //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;
+
+ if(horDscale < minHorDeci)
+ horDscale = minHorDeci;
+
+ if((int)horDscale)
+ mOVInfo.horz_deci = (int)log2f(horDscale);
+
+ if((int)verDscale)
+ mOVInfo.vert_deci = (int)log2f(verDscale);
+ }
}
bool MdpCtrl::set() {
- int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
+ int mdpVersion = MDPVersion::getInstance().getMDPVersion();
//deferred calcs, so APIs could be called in any order.
doTransform();
doDownscale();
@@ -145,7 +191,7 @@
if(utils::isYuv(whf.format)) {
normalizeCrop(mOVInfo.src_rect.x, mOVInfo.src_rect.w);
normalizeCrop(mOVInfo.src_rect.y, mOVInfo.src_rect.h);
- if(mdpVersion < qdutils::MDSS_V5) {
+ if(mdpVersion < MDSS_V5) {
utils::even_floor(mOVInfo.dst_rect.w);
utils::even_floor(mOVInfo.dst_rect.h);
}
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index edf3cec..8849984 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -356,9 +356,10 @@
const mdp_overlay& ov) {
char str[256] = {'\0'};
snprintf(str, 256,
- "%s id=%d z=%d fg=%d alpha=%d mask=%d flags=0x%x\n",
+ "%s id=%d z=%d fg=%d alpha=%d mask=%d flags=0x%x H.Deci=%d,"
+ "V.Deci=%d\n",
prefix, ov.id, ov.z_order, ov.is_fg, ov.alpha,
- ov.transp_mask, ov.flags);
+ ov.transp_mask, ov.flags, ov.horz_deci, ov.vert_deci);
strncat(buf, str, strlen(str));
getDump(buf, len, "\tsrc(msmfb_img)", ov.src);
getDump(buf, len, "\tsrc_rect(mdp_rect)", ov.src_rect);
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index cd21490..8da293d 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -44,8 +44,12 @@
struct fb_fix_screeninfo fb_finfo;
mMdpRev = 0;
- mRGBPipes = mVGPipes = 0;
+ mRGBPipes = 0;
+ mVGPipes = 0;
mDMAPipes = 0;
+ mFeatures = 0;
+ //TODO get this from driver, default for A-fam to 8
+ mMDPDownscale = 8;
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_finfo) < 0) {
ALOGE("FBIOGET_FSCREENINFO failed");
@@ -80,6 +84,7 @@
mRGBPipes = metadata.data.caps.rgb_pipes;
mVGPipes = metadata.data.caps.vig_pipes;
mDMAPipes = metadata.data.caps.dma_pipes;
+ mFeatures = metadata.data.caps.features;
}
#endif
} else {
@@ -96,7 +101,21 @@
mHasOverlay = false;
if((mMDPVersion >= MDP_V4_0) || (mMDPVersion == MDP_V_UNKNOWN))
mHasOverlay = true;
+ if(mMDPVersion >= MDSS_V5) {
+ //TODO get this from driver
+ mMDPDownscale = 4;
+ }
+
mPanelType = panel_type;
}
+
+bool MDPVersion::supportsDecimation() {
+ return mFeatures & MDP_DECIMATION_EN;
+}
+
+uint32_t MDPVersion::getMaxMDPDownscale() {
+ return mMDPDownscale;
+}
+
}; //namespace qdutils
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index 98de371..2fca640 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -52,6 +52,10 @@
MDSS_V5 = 500,
};
+enum {
+ MAX_DISPLAY_DIM = 2048,
+};
+
#define MDDI_PANEL '1'
#define EBI2_PANEL '2'
#define LCDC_PANEL '3'
@@ -76,6 +80,8 @@
uint8_t getRGBPipes() { return mRGBPipes; }
uint8_t getVGPipes() { return mVGPipes; }
uint8_t getDMAPipes() { return mDMAPipes; }
+ bool supportsDecimation();
+ uint32_t getMaxMDPDownscale();
private:
int mMDPVersion;
char mPanelType;
@@ -84,6 +90,8 @@
uint8_t mRGBPipes;
uint8_t mVGPipes;
uint8_t mDMAPipes;
+ uint32_t mFeatures;
+ uint32_t mMDPDownscale;
};
}; //namespace qdutils
#endif //INCLUDE_LIBQCOMUTILS_MDPVER