Merge "hwc: Fix bugs with mixed mode MDP comp"
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 9f91a99..bfa33ca 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -73,6 +73,8 @@
//Request an RGB pipe
ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
if(dest == ovutils::OV_INVALID) { //None available
+ ALOGE("%s: No pipes available to configure fb for dpy %d",
+ __FUNCTION__, mDpy);
return false;
}
@@ -171,11 +173,15 @@
//Request left RGB pipe
ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
if(destL == ovutils::OV_INVALID) { //None available
+ ALOGE("%s: No pipes available to configure fb for dpy %d's left"
+ " mixer", __FUNCTION__, mDpy);
return false;
}
//Request right RGB pipe
ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
if(destR == ovutils::OV_INVALID) { //None available
+ ALOGE("%s: No pipes available to configure fb for dpy %d's right"
+ " mixer", __FUNCTION__, mDpy);
return false;
}
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index cfc2558..eb46304 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -160,9 +160,6 @@
layer->compositionType = HWC_OVERLAY;
}
}
- mCachedFrame.mdpCount = mCurrentFrame.mdpCount;
- mCachedFrame.cacheCount = mCurrentFrame.fbCount;
- mCachedFrame.layerCount = ctx->listStats[mDpy].numAppLayers;
}
/*
@@ -205,13 +202,11 @@
return true;
}
MDPComp::FrameInfo::FrameInfo() {
- layerCount = 0;
- reset();
+ reset(0);
}
-void MDPComp::FrameInfo::reset() {
-
- for(int i = 0 ; i < MAX_PIPES_PER_MIXER && layerCount; i++ ) {
+void MDPComp::FrameInfo::reset(const int& numLayers) {
+ for(int i = 0 ; i < MAX_PIPES_PER_MIXER && numLayers; i++ ) {
if(mdpToLayer[i].pipeInfo) {
delete mdpToLayer[i].pipeInfo;
mdpToLayer[i].pipeInfo = NULL;
@@ -222,24 +217,50 @@
memset(&mdpToLayer, 0, sizeof(mdpToLayer));
memset(&layerToMDP, -1, sizeof(layerToMDP));
- memset(&isFBComposed, 0, sizeof(isFBComposed));
+ memset(&isFBComposed, 1, sizeof(isFBComposed));
- layerCount = 0;
+ layerCount = numLayers;
+ fbCount = numLayers;
mdpCount = 0;
- fbCount = 0;
needsRedraw = false;
fbZ = 0;
}
+void MDPComp::FrameInfo::map() {
+ // populate layer and MDP maps
+ int mdpIdx = 0;
+ for(int idx = 0; idx < layerCount; idx++) {
+ if(!isFBComposed[idx]) {
+ mdpToLayer[mdpIdx].listIndex = idx;
+ layerToMDP[idx] = mdpIdx++;
+ }
+ }
+}
+
MDPComp::LayerCache::LayerCache() {
reset();
}
void MDPComp::LayerCache::reset() {
- memset(&hnd, 0, sizeof(buffer_handle_t));
+ memset(&hnd, 0, sizeof(hnd));
mdpCount = 0;
cacheCount = 0;
layerCount = 0;
+ fbZ = -1;
+}
+
+void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
+ const int numAppLayers = list->numHwLayers - 1;
+ for(int i = 0; i < numAppLayers; i++) {
+ hnd[i] = list->hwLayers[i].handle;
+ }
+}
+
+void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
+ mdpCount = curFrame.mdpCount;
+ cacheCount = curFrame.fbCount;
+ layerCount = curFrame.layerCount;
+ fbZ = curFrame.fbZ;
}
bool MDPComp::isWidthValid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
@@ -315,31 +336,30 @@
bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ bool ret = true;
if(!isEnabled()) {
ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
- return false;
- }
-
- if(ctx->mExtDispConfiguring) {
+ ret = false;
+ } else if(ctx->mExtDispConfiguring) {
ALOGD_IF( isDebug(),"%s: External Display connection is pending",
__FUNCTION__);
- return false;
- }
-
- if(ctx->listStats[mDpy].needsAlphaScale
+ ret = false;
+ } else if(ctx->listStats[mDpy].needsAlphaScale
&& ctx->mMDP.version < qdutils::MDSS_V5) {
ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
- return false;
- }
-
- if(ctx->isPaddingRound) {
+ ret = false;
+ } else if(ctx->isPaddingRound) {
ctx->isPaddingRound = false;
ALOGD_IF(isDebug(), "%s: padding round",__FUNCTION__);
- return false;
+ ret = false;
+ } else if(sIdleFallBack) {
+ sIdleFallBack = false;
+ ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
+ ret = false;
}
- return true;
+ return ret;
}
/* Checks for conditions where all the layers marked for MDP comp cannot be
@@ -347,9 +367,7 @@
bool MDPComp::isFullFrameDoable(hwc_context_t *ctx,
hwc_display_contents_1_t* list){
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- int mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount;
- int fbNeeded = int(mCurrentFrame.fbCount != 0);
+ const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
if(mDpy > HWC_DISPLAY_PRIMARY){
ALOGD_IF(isDebug(), "%s: Cannot support External display(s)",
@@ -357,25 +375,10 @@
return false;
}
- if(mdpCount > (sMaxPipesPerMixer - fbNeeded)) {
- ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
- return false;
- }
-
- if(pipesNeeded(ctx, list) > getAvailablePipes(ctx)) {
- ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes",__FUNCTION__);
- return false;
- }
-
if(isSkipPresent(ctx, mDpy)) {
- ALOGD_IF(isDebug(), "%s: Skip layers present",__FUNCTION__);
- return false;
- }
-
- //FB composition on idle timeout
- if(sIdleFallBack) {
- sIdleFallBack = false;
- ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__);
+ ALOGD_IF(isDebug(),"%s: SKIP present: %d",
+ __FUNCTION__,
+ isSkipPresent(ctx, mDpy));
return false;
}
@@ -396,6 +399,94 @@
return false;
}
}
+
+ //If all above hard conditions are met we can do full or partial MDP comp.
+ bool ret = false;
+ if(fullMDPComp(ctx, list)) {
+ ret = true;
+ } else if (partialMDPComp(ctx, list)) {
+ ret = true;
+ }
+ return ret;
+}
+
+bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+ //Setup mCurrentFrame
+ mCurrentFrame.mdpCount = mCurrentFrame.layerCount;
+ mCurrentFrame.fbCount = 0;
+ mCurrentFrame.fbZ = -1;
+ memset(&mCurrentFrame.isFBComposed, 0, sizeof(mCurrentFrame.isFBComposed));
+
+ int mdpCount = mCurrentFrame.mdpCount;
+ if(mdpCount > sMaxPipesPerMixer) {
+ ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
+ return false;
+ }
+
+ int numPipesNeeded = pipesNeeded(ctx, list);
+ int availPipes = getAvailablePipes(ctx);
+
+ if(numPipesNeeded > availPipes) {
+ ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
+ __FUNCTION__, numPipesNeeded, availPipes);
+ return false;
+ }
+
+ return true;
+}
+
+bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
+{
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ //Setup mCurrentFrame
+ mCurrentFrame.reset(numAppLayers);
+ updateLayerCache(ctx, list);
+ updateYUV(ctx, list);
+ batchLayers(); //sets up fbZ also
+
+ int mdpCount = mCurrentFrame.mdpCount;
+ if(mdpCount > (sMaxPipesPerMixer - 1)) { // -1 since FB is used
+ ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
+ return false;
+ }
+
+ int numPipesNeeded = pipesNeeded(ctx, list);
+ int availPipes = getAvailablePipes(ctx);
+
+ if(numPipesNeeded > availPipes) {
+ ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
+ __FUNCTION__, numPipesNeeded, availPipes);
+ return false;
+ }
+
+ return true;
+}
+
+bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list){
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ mCurrentFrame.reset(numAppLayers);
+ updateYUV(ctx, list);
+ int mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount;
+ int fbNeeded = int(mCurrentFrame.fbCount != 0);
+
+ if(!isYuvPresent(ctx, mDpy)) {
+ return false;
+ }
+
+ if(mdpCount > (sMaxPipesPerMixer - fbNeeded)) {
+ ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
+ return false;
+ }
+
+ int numPipesNeeded = pipesNeeded(ctx, list);
+ int availPipes = getAvailablePipes(ctx);
+ if(numPipesNeeded > availPipes) {
+ ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
+ __FUNCTION__, numPipesNeeded, availPipes);
+ return false;
+ }
+
return true;
}
@@ -442,9 +533,14 @@
int maxBatchCount = 0;
/* All or Nothing is cached. No batching needed */
- if(!mCurrentFrame.fbCount ||
- (mCurrentFrame.fbCount == mCurrentFrame.layerCount))
+ if(!mCurrentFrame.fbCount) {
+ mCurrentFrame.fbZ = -1;
return;
+ }
+ if(!mCurrentFrame.mdpCount) {
+ mCurrentFrame.fbZ = 0;
+ return;
+ }
/* Search for max number of contiguous (cached) layers */
int i = 0;
@@ -456,6 +552,7 @@
if(count > maxBatchCount) {
maxBatchCount = count;
maxBatchStart = i - count;
+ mCurrentFrame.fbZ = maxBatchStart;
}
if(i < mCurrentFrame.layerCount) i++;
}
@@ -470,6 +567,8 @@
}
mCurrentFrame.fbCount = maxBatchCount;
+ mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
+ mCurrentFrame.fbCount;
ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
mCurrentFrame.fbCount);
@@ -481,23 +580,19 @@
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
int numCacheableLayers = 0;
- if((list->flags & HWC_GEOMETRY_CHANGED) || (isSkipPresent(ctx, mDpy))) {
- ALOGD_IF(isDebug(),"%s: No Caching: \
- GEOMETRY change: %d SKIP present: %d", __FUNCTION__,
- (list->flags & HWC_GEOMETRY_CHANGED),isSkipPresent(ctx, mDpy));
- mCachedFrame.reset();
- return;
- }
-
for(int i = 0; i < numAppLayers; i++) {
if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
numCacheableLayers++;
mCurrentFrame.isFBComposed[i] = true;
} else {
+ mCurrentFrame.isFBComposed[i] = false;
mCachedFrame.hnd[i] = list->hwLayers[i].handle;
}
}
+
mCurrentFrame.fbCount = numCacheableLayers;
+ mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
+ mCurrentFrame.fbCount;
ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__, numCacheableLayers);
}
@@ -518,14 +613,6 @@
return numAvailable;
}
-void MDPComp::resetFrameForFB(hwc_context_t* ctx,
- hwc_display_contents_1_t* list) {
- mCurrentFrame.fbCount = mCurrentFrame.layerCount;
- memset(&mCurrentFrame.isFBComposed, 1,
- sizeof(mCurrentFrame.isFBComposed));
- mCurrentFrame.needsRedraw = true;
-}
-
void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
int nYuvCount = ctx->listStats[mDpy].yuvCount;
@@ -545,22 +632,23 @@
}
}
}
+
+ mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
+ mCurrentFrame.fbCount;
ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
mCurrentFrame.fbCount);
}
-int MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
- int fbZOrder = -1;
-
+bool MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
if(!allocLayerPipes(ctx, list)) {
ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
- goto fn_exit;
+ return false;
}
+ bool fbBatch = false;
for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
- index++) {
+ index++) {
if(!mCurrentFrame.isFBComposed[index]) {
-
int mdpIndex = mCurrentFrame.layerToMDP[index];
hwc_layer_1_t* layer = &list->hwLayers[index];
@@ -570,80 +658,106 @@
if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
layer %d",__FUNCTION__, index);
- goto fn_exit;
+ return false;
}
- } else if(fbZOrder < 0) {
- fbZOrder = mdpNextZOrder++;
- };
+ } else if(fbBatch == false) {
+ mdpNextZOrder++;
+ fbBatch = true;
+ }
}
- return fbZOrder;
+ return true;
+}
- fn_exit:
- //Complete fallback to FB
- resetFrameForFB(ctx, list);
- return 0;
+bool MDPComp::programYUV(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+ if(!allocLayerPipes(ctx, list)) {
+ ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
+ return false;
+ }
+ //If we are in this block, it means we have yuv + rgb layers both
+ int mdpIdx = 0;
+ for (int index = 0; index < mCurrentFrame.layerCount; index++) {
+ if(!mCurrentFrame.isFBComposed[index]) {
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ int mdpIndex = mCurrentFrame.layerToMDP[index];
+ MdpPipeInfo* cur_pipe =
+ mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+ cur_pipe->zOrder = mdpIdx++;
+
+ if(configure(ctx, layer,
+ mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
+ ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
+ layer %d",__FUNCTION__, index);
+ return false;
+ }
+ }
+ }
+ return true;
}
int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
//reset old data
- mCurrentFrame.reset();
+ const int numLayers = ctx->listStats[mDpy].numAppLayers;
+ mCurrentFrame.reset(numLayers);
+ //Hard conditions, if not met, cannot do MDP comp
if(!isFrameDoable(ctx)) {
ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
__FUNCTION__);
+ mCurrentFrame.reset(numLayers);
+ mCachedFrame.cacheAll(list);
+ mCachedFrame.updateCounts(mCurrentFrame);
return 0;
}
- mCurrentFrame.layerCount = ctx->listStats[mDpy].numAppLayers;
-
- //Iterate layer list for cached layers
- updateLayerCache(ctx, list);
-
- //Add YUV layers to cached list
- updateYUV(ctx, list);
-
- //Optimze for bypass
- batchLayers();
-
- //list is already parsed / batched for optimal mixed mode composition.
//Check whether layers marked for MDP Composition is actually doable.
- if(!isFullFrameDoable(ctx, list)){
+ if(isFullFrameDoable(ctx, list)){
+ if(mCurrentFrame.mdpCount) {
+ mCurrentFrame.map();
+ //Acquire and Program MDP pipes
+ if(!programMDP(ctx, list)) {
+ mCurrentFrame.reset(numLayers);
+ mCachedFrame.cacheAll(list);
+ }
+ }
+ } else if(isOnlyVideoDoable(ctx, list)) {
//All layers marked for MDP comp cannot be bypassed.
//Try to compose atleast YUV layers through MDP comp and let
//all the RGB layers compose in FB
- resetFrameForFB(ctx, list);
- updateYUV(ctx, list);
- }
+ //Destination over
+ mCurrentFrame.fbZ = -1;
+ if(mCurrentFrame.fbCount)
+ mCurrentFrame.fbZ = ctx->listStats[mDpy].yuvCount;
- mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
- mCurrentFrame.fbCount;
-
- if(mCurrentFrame.mdpCount) {
- // populate layer and MDP maps
- for(int idx = 0, mdpIdx = 0; idx < mCurrentFrame.layerCount; idx++) {
- if(!mCurrentFrame.isFBComposed[idx]) {
- mCurrentFrame.mdpToLayer[mdpIdx].listIndex = idx;
- mCurrentFrame.layerToMDP[idx] = mdpIdx++;
- }
+ mCurrentFrame.map();
+ if(!programYUV(ctx, list)) {
+ mCurrentFrame.reset(numLayers);
+ mCachedFrame.cacheAll(list);
}
- //Acquire and Program MDP pipes
- mCurrentFrame.fbZ = programMDP(ctx, list);
+ } else {
+ mCurrentFrame.reset(numLayers);
+ mCachedFrame.cacheAll(list);
}
/* Any change in composition types needs an FB refresh*/
if(mCurrentFrame.fbCount &&
- ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) ||
- (mCurrentFrame.fbCount != mCachedFrame.cacheCount) ||
- !mCurrentFrame.mdpCount)) {
+ ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) ||
+ (mCurrentFrame.fbCount != mCachedFrame.cacheCount) ||
+ (mCurrentFrame.fbZ != mCachedFrame.fbZ) ||
+ (!mCurrentFrame.mdpCount) ||
+ (list->flags & HWC_GEOMETRY_CHANGED) ||
+ isSkipPresent(ctx, mDpy) ||
+ (mDpy > HWC_DISPLAY_PRIMARY))) {
mCurrentFrame.needsRedraw = true;
}
//UpdateLayerFlags
setMDPCompLayerFlags(ctx, list);
+ mCachedFrame.updateCounts(mCurrentFrame);
if(isDebug()) {
+ ALOGD("GEOMETRY change: %d", (list->flags & HWC_GEOMETRY_CHANGED));
android::String8 sDump("");
dump(sDump);
ALOGE("%s",sDump.string());
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 7970cd3..4aedd77 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -93,7 +93,8 @@
/* c'tor */
FrameInfo();
/* clear old frame data */
- void reset();
+ void reset(const int& numLayers);
+ void map();
};
/* cached data */
@@ -101,12 +102,15 @@
int layerCount;
int mdpCount;
int cacheCount;
+ int fbZ;
buffer_handle_t hnd[MAX_NUM_LAYERS];
/* c'tor */
LayerCache();
/* clear caching info*/
void reset();
+ void cacheAll(hwc_display_contents_1_t* list);
+ void updateCounts(const FrameInfo&);
};
/* No of pipes needed for Framebuffer */
@@ -121,7 +125,6 @@
virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& pipeLayerPair) = 0;
-
/* set/reset flags for MDPComp */
void setMDPCompLayerFlags(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
@@ -132,6 +135,12 @@
bool isFrameDoable(hwc_context_t *ctx);
/* checks for conditions where RGB layers cannot be bypassed */
bool isFullFrameDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ /* checks if full MDP comp can be done */
+ bool fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ /* check if we can use layer cache to do at least partial MDP comp */
+ bool partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ /* checks for conditions where only video can be bypassed */
+ 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);
@@ -145,16 +154,14 @@
bool isWidthValid(hwc_context_t *ctx, hwc_layer_1_t *layer);
/* tracks non updating layers*/
void updateLayerCache(hwc_context_t* ctx, hwc_display_contents_1_t* list);
- /* resets cache for complete fallback */
- void resetFrameForFB(hwc_context_t* ctx, hwc_display_contents_1_t* list);
/* optimize layers for mdp comp*/
void batchLayers();
/* gets available pipes for mdp comp */
int getAvailablePipes(hwc_context_t* ctx);
/* updates cache map with YUV info */
void updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list);
- int programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-
+ bool programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ bool programYUV(hwc_context_t *ctx, hwc_display_contents_1_t* list);
int mDpy;
static bool sEnabled;