Merge "qdutils: initialize debug_fps_metadata.curr_frame before counting fps"
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 10d372a..30754dd 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -247,9 +247,9 @@
return -EINVAL;
int err = 0;
private_handle_t* hnd = (private_handle_t*)handle;
- IMemAlloc* memalloc = getAllocator(hnd->flags);
if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
+ IMemAlloc* memalloc = getAllocator(hnd->flags);
if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
err = memalloc->clean_buffer((void*)hnd->base,
hnd->size, hnd->offset, hnd->fd,
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 113e916..5fd7564 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -123,6 +123,7 @@
}
ctx->mAD->reset();
+ MDPComp::reset();
}
//clear prev layer prop flags and realloc for current frame
diff --git a/libhwcomposer/hwc_ad.cpp b/libhwcomposer/hwc_ad.cpp
index 9ac8958..c2ea4ee 100644
--- a/libhwcomposer/hwc_ad.cpp
+++ b/libhwcomposer/hwc_ad.cpp
@@ -118,20 +118,34 @@
}
close(adFd);
} else {
- ALOGE("%s: Failed to open /sys/class/graphics/fb%d/ad with error %s",
+ ALOGD("%s: /sys/class/graphics/fb%d/ad could not be opened : %s",
__func__, wbFbNum, strerror(errno));
}
return ret;
}
-AssertiveDisplay::AssertiveDisplay() :mWbFd(-1), mDoable(false),
- mFeatureEnabled(false), mDest(overlay::utils::OV_INVALID) {
+AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) : mWbFd(-1),
+ mDoable(false), mFeatureEnabled(false),
+ mDest(overlay::utils::OV_INVALID) {
int fd = openWbFb();
if(fd >= 0) {
+ //Values in ad node:
//-1 means feature is disabled on device
// 0 means feature exists but turned off, will be turned on by hwc
// 1 means feature is turned on by hwc
- if(adRead() >= 0) {
+ // Plus, we do this feature only on split primary displays.
+ // Plus, we do this feature only if ro.qcom.ad=2
+
+ char property[PROPERTY_VALUE_MAX];
+ const int ENABLED = 2;
+ int val = 0;
+
+ if(property_get("ro.qcom.ad", property, "0") > 0) {
+ val = atoi(property);
+ }
+
+ if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
+ val == ENABLED) {
ALOGD_IF(DEBUG, "Assertive display feature supported");
mFeatureEnabled = true;
}
diff --git a/libhwcomposer/hwc_ad.h b/libhwcomposer/hwc_ad.h
index 38b724d..c745b15 100644
--- a/libhwcomposer/hwc_ad.h
+++ b/libhwcomposer/hwc_ad.h
@@ -39,7 +39,7 @@
class AssertiveDisplay {
public:
- AssertiveDisplay();
+ AssertiveDisplay(hwc_context_t *ctx);
void markDoable(hwc_context_t *ctx, const hwc_display_contents_1_t* list);
bool prepare(hwc_context_t *ctx, const hwc_rect_t& crop,
const overlay::utils::Whf& whf,
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index a395ee0..dbb4413 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -223,24 +223,18 @@
if (!useCopybitForYUV && ctx->listStats[dpy].yuvCount)
return true;
- // numAppLayers-1, as we iterate till 0th layer index
- for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
- private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
-
- if ((hnd->bufferType == BUFFER_TYPE_VIDEO && useCopybitForYUV) ||
- (hnd->bufferType == BUFFER_TYPE_UI && useCopybitForRGB)) {
+ mCopyBitDraw = false;
+ if (useCopybitForRGB &&
+ (useCopybitForYUV || !ctx->listStats[dpy].yuvCount)) {
+ mCopyBitDraw = true;
+ // numAppLayers-1, as we iterate till 0th layer index
+ // Mark all layers to be drawn by copybit
+ for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
layerProp[i].mFlags |= HWC_COPYBIT;
list->hwLayers[i].compositionType = HWC_OVERLAY;
- mCopyBitDraw = true;
- } else {
- // We currently cannot mix copybit layers with layers marked to
- // be drawn on the framebuffer or that are on the layer cache.
- mCopyBitDraw = false;
- //There is no need to reset layer properties here as we return in
- //draw if mCopyBitDraw is false
- break;
}
}
+
return true;
}
@@ -364,6 +358,27 @@
// if needed in the future
src.vert_padding = 0;
+ int layerTransform = layer->transform ;
+ // When flip and rotation(90) are present alter the flip,
+ // as GPU is doing the flip and rotation in opposite order
+ // to that of MDP3.0
+ // For 270 degrees, we get 90 + (H+V) which is same as doing
+ // flip first and then rotation (H+V) + 90
+ if (qdutils::MDPVersion::getInstance().getMDPVersion() < 400) {
+ if (((layer->transform& HAL_TRANSFORM_FLIP_H) ||
+ (layer->transform & HAL_TRANSFORM_FLIP_V)) &&
+ (layer->transform & HAL_TRANSFORM_ROT_90) &&
+ !(layer->transform == HAL_TRANSFORM_ROT_270)){
+ if(layer->transform & HAL_TRANSFORM_FLIP_H){
+ layerTransform ^= HAL_TRANSFORM_FLIP_H;
+ layerTransform |= HAL_TRANSFORM_FLIP_V;
+ }
+ if(layer->transform & HAL_TRANSFORM_FLIP_V){
+ layerTransform ^= HAL_TRANSFORM_FLIP_V;
+ layerTransform |= HAL_TRANSFORM_FLIP_H;
+ }
+ }
+ }
// Copybit source rect
hwc_rect_t sourceCrop = layer->sourceCrop;
copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top,
@@ -519,7 +534,7 @@
copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
renderBuffer->height);
copybit->set_parameter(copybit, COPYBIT_TRANSFORM,
- layer->transform);
+ layerTransform);
//TODO: once, we are able to read layer alpha, update this
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
copybit->set_parameter(copybit, COPYBIT_BLEND_MODE,
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 2337b2a..53b3d18 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -37,12 +37,11 @@
namespace ovutils = overlay::utils;
-IFBUpdate* IFBUpdate::getObject(const int& width, const int& rightSplit,
- const int& dpy) {
- if(width > MAX_DISPLAY_DIM || rightSplit) {
- return new FBUpdateHighRes(dpy);
+IFBUpdate* IFBUpdate::getObject(hwc_context_t *ctx, const int& dpy) {
+ if(isDisplaySplit(ctx, dpy)) {
+ return new FBUpdateSplit(dpy);
}
- return new FBUpdateLowRes(dpy);
+ return new FBUpdateNonSplit(dpy);
}
inline void IFBUpdate::reset() {
@@ -51,14 +50,14 @@
}
//================= Low res====================================
-FBUpdateLowRes::FBUpdateLowRes(const int& dpy): IFBUpdate(dpy) {}
+FBUpdateNonSplit::FBUpdateNonSplit(const int& dpy): IFBUpdate(dpy) {}
-inline void FBUpdateLowRes::reset() {
+inline void FBUpdateNonSplit::reset() {
IFBUpdate::reset();
mDest = ovutils::OV_INVALID;
}
-bool FBUpdateLowRes::preRotateExtDisplay(hwc_context_t *ctx,
+bool FBUpdateNonSplit::preRotateExtDisplay(hwc_context_t *ctx,
ovutils::Whf &info,
hwc_rect_t& sourceCrop,
ovutils::eMdpFlags& mdpFlags,
@@ -82,7 +81,7 @@
return true;
}
-bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
+bool FBUpdateNonSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
int fbZorder) {
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
@@ -94,7 +93,7 @@
}
// Configure
-bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
int fbZorder) {
bool ret = false;
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
@@ -186,7 +185,7 @@
return ret;
}
-bool FBUpdateLowRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
+bool FBUpdateNonSplit::draw(hwc_context_t *ctx, private_handle_t *hnd)
{
if(!mModeOn) {
return true;
@@ -210,16 +209,16 @@
}
//================= High res====================================
-FBUpdateHighRes::FBUpdateHighRes(const int& dpy): IFBUpdate(dpy) {}
+FBUpdateSplit::FBUpdateSplit(const int& dpy): IFBUpdate(dpy) {}
-inline void FBUpdateHighRes::reset() {
+inline void FBUpdateSplit::reset() {
IFBUpdate::reset();
mDestLeft = ovutils::OV_INVALID;
mDestRight = ovutils::OV_INVALID;
mRot = NULL;
}
-bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
+bool FBUpdateSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
int fbZorder) {
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
@@ -232,7 +231,7 @@
}
// Configure
-bool FBUpdateHighRes::configure(hwc_context_t *ctx,
+bool FBUpdateSplit::configure(hwc_context_t *ctx,
hwc_display_contents_1 *list, int fbZorder) {
bool ret = false;
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
@@ -355,7 +354,7 @@
return ret;
}
-bool FBUpdateHighRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
+bool FBUpdateSplit::draw(hwc_context_t *ctx, private_handle_t *hnd)
{
if(!mModeOn) {
return true;
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index 3c76efe..0e3f29e 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -45,8 +45,7 @@
//Reset values
virtual void reset();
//Factory method that returns a low-res or high-res version
- static IFBUpdate *getObject(const int& width, const int& rightSplit,
- const int& dpy);
+ static IFBUpdate *getObject(hwc_context_t *ctx, const int& dpy);
protected:
const int mDpy; // display to update
@@ -54,11 +53,11 @@
overlay::Rotator *mRot;
};
-//Low resolution (<= 2048) panel handler.
-class FBUpdateLowRes : public IFBUpdate {
+//Non-Split panel handler.
+class FBUpdateNonSplit : public IFBUpdate {
public:
- explicit FBUpdateLowRes(const int& dpy);
- virtual ~FBUpdateLowRes() {};
+ explicit FBUpdateNonSplit(const int& dpy);
+ virtual ~FBUpdateNonSplit() {};
bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
int fbZorder);
bool draw(hwc_context_t *ctx, private_handle_t *hnd);
@@ -74,11 +73,11 @@
ovutils::eDest mDest; //pipe to draw on
};
-//High resolution (> 2048) panel handler.
-class FBUpdateHighRes : public IFBUpdate {
+//Split panel handler.
+class FBUpdateSplit : public IFBUpdate {
public:
- explicit FBUpdateHighRes(const int& dpy);
- virtual ~FBUpdateHighRes() {};
+ explicit FBUpdateSplit(const int& dpy);
+ virtual ~FBUpdateSplit() {};
bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
int fbZorder);
bool draw(hwc_context_t *ctx, private_handle_t *hnd);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index f2217b9..7ec99c1 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -42,13 +42,14 @@
bool MDPComp::sEnabled = false;
bool MDPComp::sEnableMixedMode = true;
int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
+float MDPComp::sMaxBw = 2.3f;
+uint32_t MDPComp::sCompBytesClaimed = 0;
-MDPComp* MDPComp::getObject(const int& width, const int& rightSplit,
- const int& dpy) {
- if(width > MAX_DISPLAY_DIM || rightSplit) {
- return new MDPCompHighRes(dpy);
+MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
+ if(isDisplaySplit(ctx, dpy)) {
+ return new MDPCompSplit(dpy);
}
- return new MDPCompLowRes(dpy);
+ return new MDPCompNonSplit(dpy);
}
MDPComp::MDPComp(int dpy):mDpy(dpy){};
@@ -125,6 +126,13 @@
sMaxPipesPerMixer = min(val, MAX_PIPES_PER_MIXER);
}
+ if(property_get("debug.mdpcomp.bw", property, "0") > 0) {
+ float val = atof(property);
+ if(val > 0.0f) {
+ sMaxBw = val;
+ }
+ }
+
if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
// Idle invalidation is not necessary on command mode panels
long idle_timeout = DEFAULT_IDLE_TIME;
@@ -497,6 +505,12 @@
return false;
}
+ uint32_t size = calcMDPBytesRead(ctx, list);
+ if(!bandwidthCheck(ctx, size)) {
+ ALOGD_IF(isDebug(), "%s: Exceeds bandwidth",__FUNCTION__);
+ return false;
+ }
+
return true;
}
@@ -525,6 +539,12 @@
return false;
}
+ uint32_t size = calcMDPBytesRead(ctx, list);
+ if(!bandwidthCheck(ctx, size)) {
+ ALOGD_IF(isDebug(), "%s: Exceeds bandwidth",__FUNCTION__);
+ return false;
+ }
+
return true;
}
@@ -552,6 +572,12 @@
return false;
}
+ uint32_t size = calcMDPBytesRead(ctx, list);
+ if(!bandwidthCheck(ctx, size)) {
+ ALOGD_IF(isDebug(), "%s: Exceeds bandwidth",__FUNCTION__);
+ return false;
+ }
+
return true;
}
@@ -753,7 +779,46 @@
return true;
}
+uint32_t MDPComp::calcMDPBytesRead(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ uint32_t size = 0;
+
+ for (uint32_t i = 0; i < list->numHwLayers - 1; i++) {
+ if(!mCurrentFrame.isFBComposed[i]) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ hwc_rect_t crop = layer->sourceCrop;
+ float bpp = ((float)hnd->size) / (hnd->width * hnd->height);
+ size += bpp * ((crop.right - crop.left) *
+ (crop.bottom - crop.top));
+ }
+ }
+
+ if(mCurrentFrame.fbCount) {
+ hwc_layer_1_t* layer = &list->hwLayers[list->numHwLayers - 1];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ size += hnd->size;
+ }
+
+ return size;
+}
+
+bool MDPComp::bandwidthCheck(hwc_context_t *ctx, const uint32_t& size) {
+ //Will be added for other targets if we run into bandwidth issues and when
+ //we have profiling data to set an upper limit.
+ if(qdutils::MDPVersion::getInstance().is8x74v2()) {
+ const uint32_t ONE_GIG = 1024 * 1024 * 1024;
+ double panelRefRate =
+ 1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
+ if((size + sCompBytesClaimed) > ((sMaxBw / panelRefRate) * ONE_GIG)) {
+ return false;
+ }
+ }
+ return true;
+}
+
int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+ int ret = 0;
const int numLayers = ctx->listStats[mDpy].numAppLayers;
//reset old data
@@ -765,7 +830,8 @@
mCachedFrame.updateCounts(mCurrentFrame);
ALOGD_IF(isDebug(), "%s: Number of App layers exceeded the limit ",
__FUNCTION__);
- return -1;
+ ret = -1;
+ goto exit;
}
//Hard conditions, if not met, cannot do MDP comp
@@ -773,7 +839,8 @@
ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
__FUNCTION__);
reset(numLayers, list);
- return -1;
+ ret = -1;
+ goto exit;
}
//Check whether layers marked for MDP Composition is actually doable.
@@ -785,13 +852,17 @@
mCurrentFrame.fbZ)) {
ALOGE("%s configure framebuffer failed", __func__);
reset(numLayers, list);
- return -1;
+ ctx->mOverlay->clear(mDpy);
+ ret = -1;
+ goto exit;
}
}
//Acquire and Program MDP pipes
if(!programMDP(ctx, list)) {
reset(numLayers, list);
- return -1;
+ ctx->mOverlay->clear(mDpy);
+ ret = -1;
+ goto exit;
} else { //Success
//Any change in composition types needs an FB refresh
mCurrentFrame.needsRedraw = false;
@@ -822,16 +893,21 @@
if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
ALOGE("%s configure framebuffer failed", __func__);
reset(numLayers, list);
- return -1;
+ ctx->mOverlay->clear(mDpy);
+ ret = -1;
+ goto exit;
}
}
if(!programYUV(ctx, list)) {
reset(numLayers, list);
- return -1;
+ ctx->mOverlay->clear(mDpy);
+ ret = -1;
+ goto exit;
}
} else {
reset(numLayers, list);
- return -1;
+ ret = -1;
+ goto exit;
}
//UpdateLayerFlags
@@ -846,18 +922,20 @@
ALOGE("%s",sDump.string());
}
- return 0;
+exit:
+ sCompBytesClaimed += calcMDPBytesRead(ctx, list);
+ return ret;
}
-//=============MDPCompLowRes===================================================
+//=============MDPCompNonSplit===================================================
/*
* Configures pipe(s) for MDP composition
*/
-int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& PipeLayerPair) {
- MdpPipeInfoLowRes& mdp_info =
- *(static_cast<MdpPipeInfoLowRes*>(PipeLayerPair.pipeInfo));
+ MdpPipeInfoNonSplit& mdp_info =
+ *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
eIsFg isFg = IS_FG_OFF;
@@ -866,11 +944,11 @@
ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
__FUNCTION__, layer, zOrder, dest);
- return configureLowRes(ctx, layer, mDpy, mdpFlags, zOrder, isFg, dest,
+ return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, isFg, dest,
&PipeLayerPair.rot);
}
-bool MDPCompLowRes::arePipesAvailable(hwc_context_t *ctx,
+bool MDPCompNonSplit::arePipesAvailable(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
overlay::Overlay& ov = *ctx->mOverlay;
int numPipesNeeded = mCurrentFrame.mdpCount;
@@ -889,7 +967,7 @@
return true;
}
-bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
+bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
for(int index = 0; index < mCurrentFrame.layerCount; index++) {
@@ -899,9 +977,9 @@
private_handle_t *hnd = (private_handle_t *)layer->handle;
int mdpIndex = mCurrentFrame.layerToMDP[index];
PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
- info.pipeInfo = new MdpPipeInfoLowRes;
+ info.pipeInfo = new MdpPipeInfoNonSplit;
info.rot = NULL;
- MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
+ MdpPipeInfoNonSplit& pipe_info = *(MdpPipeInfoNonSplit*)info.pipeInfo;
ePipeType type = MDPCOMP_OV_ANY;
if(isYuvBuffer(hnd)) {
@@ -922,7 +1000,7 @@
return true;
}
-bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
if(!isEnabled()) {
ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
@@ -960,8 +1038,8 @@
int mdpIndex = mCurrentFrame.layerToMDP[i];
- MdpPipeInfoLowRes& pipe_info =
- *(MdpPipeInfoLowRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+ MdpPipeInfoNonSplit& pipe_info =
+ *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
ovutils::eDest dest = pipe_info.index;
if(dest == ovutils::OV_INVALID) {
ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
@@ -979,13 +1057,6 @@
int fd = hnd->fd;
uint32_t offset = hnd->offset;
- if(ctx->mAD->isModeOn()) {
- if(ctx->mAD->draw(ctx, fd, offset)) {
- fd = ctx->mAD->getDstFd(ctx);
- offset = ctx->mAD->getDstOffset(ctx);
- }
- }
-
Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
if(rot) {
if(!rot->queueBuffer(fd, offset))
@@ -1004,9 +1075,9 @@
return true;
}
-//=============MDPCompHighRes===================================================
+//=============MDPCompSplit===================================================
-int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
+int MDPCompSplit::pipesNeeded(hwc_context_t *ctx,
hwc_display_contents_1_t* list,
int mixer) {
int pipesNeeded = 0;
@@ -1028,7 +1099,7 @@
return pipesNeeded;
}
-bool MDPCompHighRes::arePipesAvailable(hwc_context_t *ctx,
+bool MDPCompSplit::arePipesAvailable(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
overlay::Overlay& ov = *ctx->mOverlay;
@@ -1050,8 +1121,8 @@
return true;
}
-bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoHighRes& pipe_info,
+bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+ MdpPipeInfoSplit& pipe_info,
ePipeType type) {
const int xres = ctx->dpyAttr[mDpy].xres;
const int lSplit = getLeftSplit(ctx, mDpy);
@@ -1075,7 +1146,7 @@
return true;
}
-bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx,
+bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
@@ -1085,9 +1156,9 @@
private_handle_t *hnd = (private_handle_t *)layer->handle;
int mdpIndex = mCurrentFrame.layerToMDP[index];
PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
- info.pipeInfo = new MdpPipeInfoHighRes;
+ info.pipeInfo = new MdpPipeInfoSplit;
info.rot = NULL;
- MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
+ MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
ePipeType type = MDPCOMP_OV_ANY;
if(isYuvBuffer(hnd)) {
@@ -1110,10 +1181,10 @@
/*
* Configures pipe(s) for MDP composition
*/
-int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& PipeLayerPair) {
- MdpPipeInfoHighRes& mdp_info =
- *(static_cast<MdpPipeInfoHighRes*>(PipeLayerPair.pipeInfo));
+ MdpPipeInfoSplit& mdp_info =
+ *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
eIsFg isFg = IS_FG_OFF;
eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
@@ -1123,11 +1194,11 @@
ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
"dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
- return configureHighRes(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg, lDest,
+ return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg, lDest,
rDest, &PipeLayerPair.rot);
}
-bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
if(!isEnabled()) {
ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
@@ -1169,8 +1240,8 @@
int mdpIndex = mCurrentFrame.layerToMDP[i];
- MdpPipeInfoHighRes& pipe_info =
- *(MdpPipeInfoHighRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+ MdpPipeInfoSplit& pipe_info =
+ *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
ovutils::eDest indexL = pipe_info.lIndex;
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 2f1670b..869eee7 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -46,13 +46,13 @@
/* dumpsys */
void dump(android::String8& buf);
- static MDPComp* getObject(const int& width, const int& rightSplit,
- const int& dpy);
+ static MDPComp* getObject(hwc_context_t *ctx, const int& dpy);
/* Handler to invoke frame redraw on Idle Timer expiry */
static void timeout_handler(void *udata);
/* Initialize MDP comp*/
static bool init(hwc_context_t *ctx);
static void resetIdleFallBack() { sIdleFallBack = false; }
+ static void reset() { sCompBytesClaimed = 0; };
protected:
enum ePipeType {
@@ -142,6 +142,11 @@
bool isOnlyVideoDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list);
/* checks for conditions where YUV layers cannot be bypassed */
bool isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
+ /* calcs bytes read by MDP for a given frame */
+ uint32_t calcMDPBytesRead(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* checks if the required bandwidth exceeds a certain max */
+ bool bandwidthCheck(hwc_context_t *ctx, const uint32_t& size);
/* set up Border fill as Base pipe */
static bool setupBasePipe(hwc_context_t*);
@@ -167,21 +172,26 @@
static bool sDebugLogs;
static bool sIdleFallBack;
static int sMaxPipesPerMixer;
+ //Max bandwidth. Value is in GBPS. For ex: 2.3 means 2.3GBPS
+ static float sMaxBw;
+ //Tracks composition bytes claimed. Represented as the total w*h*bpp
+ //going to MDP mixers
+ static uint32_t sCompBytesClaimed;
static IdleInvalidator *idleInvalidator;
struct FrameInfo mCurrentFrame;
struct LayerCache mCachedFrame;
};
-class MDPCompLowRes : public MDPComp {
+class MDPCompNonSplit : public MDPComp {
public:
- explicit MDPCompLowRes(int dpy):MDPComp(dpy){};
- virtual ~MDPCompLowRes(){};
+ explicit MDPCompNonSplit(int dpy):MDPComp(dpy){};
+ virtual ~MDPCompNonSplit(){};
virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
private:
- struct MdpPipeInfoLowRes : public MdpPipeInfo {
+ struct MdpPipeInfoNonSplit : public MdpPipeInfo {
ovutils::eDest index;
- virtual ~MdpPipeInfoLowRes() {};
+ virtual ~MdpPipeInfoNonSplit() {};
};
/* configure's overlay pipes for the frame */
@@ -197,20 +207,20 @@
hwc_display_contents_1_t* list);
};
-class MDPCompHighRes : public MDPComp {
+class MDPCompSplit : public MDPComp {
public:
- explicit MDPCompHighRes(int dpy):MDPComp(dpy){};
- virtual ~MDPCompHighRes(){};
+ explicit MDPCompSplit(int dpy):MDPComp(dpy){};
+ virtual ~MDPCompSplit(){};
virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
private:
- struct MdpPipeInfoHighRes : public MdpPipeInfo {
+ struct MdpPipeInfoSplit : public MdpPipeInfo {
ovutils::eDest lIndex;
ovutils::eDest rIndex;
- virtual ~MdpPipeInfoHighRes() {};
+ virtual ~MdpPipeInfoSplit() {};
};
bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoHighRes& pipe_info, ePipeType type);
+ MdpPipeInfoSplit& pipe_info, ePipeType type);
/* configure's overlay pipes for the frame */
virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 5590798..a44924b 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -48,11 +48,8 @@
static void setup(hwc_context_t* ctx, int dpy)
{
- const int rSplit = 0; //Even split for external if at all
- ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx->dpyAttr[dpy].xres,
- rSplit, dpy);
- ctx->mMDPComp[dpy] = MDPComp::getObject(ctx->dpyAttr[dpy].xres,
- rSplit, dpy);
+ ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy);
+ ctx->mMDPComp[dpy] = MDPComp::getObject(ctx, dpy);
int compositionType =
qdutils::QCCompositionType::getInstance().getCompositionType();
if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index ffaa9cb..5ea79b5 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -129,7 +129,6 @@
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
- const int rightSplit = qdutils::MDPVersion::getInstance().getRightSplit();
overlay::Overlay::initOverlay();
ctx->mOverlay = overlay::Overlay::getInstance();
ctx->mRotMgr = new RotMgr();
@@ -138,8 +137,7 @@
//For external it could get created and destroyed multiple times depending
//on what external we connect to.
ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
- IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
- rightSplit, HWC_DISPLAY_PRIMARY);
+ IFBUpdate::getObject(ctx, HWC_DISPLAY_PRIMARY);
// Check if the target supports copybit compostion (dyn/mdp/c2d) to
// decide if we need to open the copybit module.
@@ -164,8 +162,7 @@
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false;
ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
- MDPComp::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
- rightSplit, HWC_DISPLAY_PRIMARY);
+ MDPComp::getObject(ctx, HWC_DISPLAY_PRIMARY);
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
@@ -174,7 +171,7 @@
}
MDPComp::init(ctx);
- ctx->mAD = new AssertiveDisplay();
+ ctx->mAD = new AssertiveDisplay(ctx);
ctx->vstate.enable = false;
ctx->vstate.fakevsync = false;
@@ -1193,7 +1190,7 @@
}
}
-int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
+int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
eIsFg& isFg, const eDest& dest, Rotator **rot) {
@@ -1253,13 +1250,6 @@
setMdpFlags(layer, mdpFlags, downscale, transform);
trimLayer(ctx, dpy, transform, crop, dst);
- //Will do something only if feature enabled and conditions suitable
- //hollow call otherwise
- if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
- overlay::Writeback *wb = overlay::Writeback::getInstance();
- whf.format = wb->getOutputFormat();
- }
-
if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
*rot = ctx->mRotMgr->getNext();
@@ -1291,7 +1281,36 @@
return 0;
}
-int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
+//Helper to 1) Ensure crops dont have gaps 2) Ensure L and W are even
+static void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,
+ private_handle_t *hnd) {
+ if(cropL.right - cropL.left) {
+ if(isYuvBuffer(hnd)) {
+ //Always safe to even down left
+ ovutils::even_floor(cropL.left);
+ //If right is even, automatically width is even, since left is
+ //already even
+ ovutils::even_floor(cropL.right);
+ }
+ //Make sure there are no gaps between left and right splits if the layer
+ //is spread across BOTH halves
+ if(cropR.right - cropR.left) {
+ cropR.left = cropL.right;
+ }
+ }
+
+ if(cropR.right - cropR.left) {
+ if(isYuvBuffer(hnd)) {
+ //Always safe to even down left
+ ovutils::even_floor(cropR.left);
+ //If right is even, automatically width is even, since left is
+ //already even
+ ovutils::even_floor(cropR.right);
+ }
+ }
+}
+
+int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
eIsFg& isFg, const eDest& lDest, const eDest& rDest,
Rotator **rot) {
@@ -1339,6 +1358,12 @@
setMdpFlags(layer, mdpFlagsL, 0, transform);
+
+ if(lDest != OV_INVALID && rDest != OV_INVALID) {
+ //Enable overfetch
+ setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
+ }
+
trimLayer(ctx, dpy, transform, crop, dst);
//Will do something only if feature enabled and conditions suitable
@@ -1366,8 +1391,8 @@
eMdpFlags mdpFlagsR = mdpFlagsL;
setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER);
- hwc_rect_t tmp_cropL, tmp_dstL;
- hwc_rect_t tmp_cropR, tmp_dstR;
+ hwc_rect_t tmp_cropL = {0}, tmp_dstL = {0};
+ hwc_rect_t tmp_cropR = {0}, tmp_dstR = {0};
const int lSplit = getLeftSplit(ctx, dpy);
@@ -1384,6 +1409,8 @@
qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
}
+ sanitizeSourceCrop(tmp_cropL, tmp_cropR, hnd);
+
//When buffer is H-flipped, contents of mixer config also needs to swapped
//Not needed if the layer is confined to one half of the screen.
//If rotator has been used then it has also done the flips, so ignore them.
@@ -1466,6 +1493,18 @@
return lSplit;
}
+bool isDisplaySplit(hwc_context_t* ctx, int dpy) {
+ if(ctx->dpyAttr[dpy].xres > qdutils::MAX_DISPLAY_DIM) {
+ return true;
+ }
+ //For testing we could split primary via device tree values
+ if(dpy == HWC_DISPLAY_PRIMARY &&
+ qdutils::MDPVersion::getInstance().getRightSplit()) {
+ return true;
+ }
+ return false;
+}
+
void BwcPM::setBwc(hwc_context_t *ctx, const hwc_rect_t& crop,
const hwc_rect_t& dst, const int& transform,
ovutils::eMdpFlags& mdpFlags) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 5695f28..d77673b 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -233,13 +233,13 @@
hwc_rect_t& crop);
//Routine to configure low resolution panels (<= 2048 width)
-int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
+int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
ovutils::eIsFg& isFg, const ovutils::eDest& dest,
overlay::Rotator **rot);
//Routine to configure high resolution panels (> 2048 width)
-int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
+int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
ovutils::eIsFg& isFg, const ovutils::eDest& lDest,
const ovutils::eDest& rDest, overlay::Rotator **rot);
@@ -254,6 +254,8 @@
int getLeftSplit(hwc_context_t *ctx, const int& dpy);
+bool isDisplaySplit(hwc_context_t* ctx, int dpy);
+
// Inline utility functions
static inline bool isSkipLayer(const hwc_layer_1_t* l) {
return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index e49a50c..a9b7e6a 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -77,6 +77,10 @@
#define MDP_OV_PIPE_FORCE_DMA 0x4000
#endif
+#ifndef MDSS_MDP_DUAL_PIPE
+#define MDSS_MDP_DUAL_PIPE 0x200
+#endif
+
#define FB_DEVICE_TEMPLATE "/dev/graphics/fb%u"
namespace overlay {
@@ -265,6 +269,7 @@
OV_MDSS_MDP_RIGHT_MIXER = MDSS_MDP_RIGHT_MIXER,
OV_MDP_PP_EN = MDP_OVERLAY_PP_CFG_EN,
OV_MDSS_MDP_BWC_EN = MDP_BWC_EN,
+ OV_MDSS_MDP_DUAL_PIPE = MDSS_MDP_DUAL_PIPE,
};
enum eZorder {
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 1dd317f..4a695d3 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -166,5 +166,12 @@
return false;
}
+bool MDPVersion::is8x74v2() {
+ if( mMdpRev >= MDSS_MDP_HW_REV_102 && mMdpRev < MDSS_MDP_HW_REV_103) {
+ return true;
+ }
+ return false;
+}
+
}; //namespace qdutils
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index 316899f..8d23b2d 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -54,9 +54,10 @@
};
enum mdp_rev {
- MDSS_MDP_HW_REV_100 = 0x10000000,
+ MDSS_MDP_HW_REV_100 = 0x10000000, //8974 v1
MDSS_MDP_HW_REV_101 = 0x10010000, //8x26
- MDSS_MDP_HW_REV_102 = 0x10020000,
+ MDSS_MDP_HW_REV_102 = 0x10020000, //8974 v2
+ MDSS_MDP_HW_REV_103 = 0x10030000, //Future
};
enum {
@@ -101,6 +102,7 @@
uint32_t getMaxMDPDownscale();
bool supportsBWC();
bool is8x26();
+ bool is8x74v2();
int getLeftSplit() { return mSplit.left(); }
int getRightSplit() { return mSplit.right(); }
private: