hwc: Implement mixed mode composition.
With this change we are moving MDP composition from all-or-nothing
implementation to mixed mode implementation where layers can
partially be composited through MDP and while rest of the layers are
composed / cached in framebuffer.
- Mixed mode design is based on layer caching
- Mixed mode path is configured only when non-bypassing
layers are cached.
- Never allow mixed mode when FB needs to be udpated.
- If we cannot bypass all MDP comp marked layers, bail
out completely.
Change-Id: Ie08f39db07e032b537f042d0d2bfe772ebfed049
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index e8559ac..30178a0 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -35,20 +35,44 @@
bool MDPComp::sIdleFallBack = false;
bool MDPComp::sDebugLogs = false;
bool MDPComp::sEnabled = false;
+int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
-MDPComp* MDPComp::getObject(const int& width) {
+MDPComp* MDPComp::getObject(const int& width, int dpy) {
if(width <= MAX_DISPLAY_DIM) {
- return new MDPCompLowRes();
+ return new MDPCompLowRes(dpy);
} else {
- return new MDPCompHighRes();
+ return new MDPCompHighRes(dpy);
}
}
+MDPComp::MDPComp(int dpy):mDpy(dpy){};
+
void MDPComp::dump(android::String8& buf)
{
- dumpsys_log(buf, " MDP Composition: ");
- dumpsys_log(buf, "MDPCompState=%d\n", mState);
- //XXX: Log more info
+ dumpsys_log(buf,"HWC Map for Dpy: %s \n",
+ mDpy ? "\"EXTERNAL\"" : "\"PRIMARY\"");
+ dumpsys_log(buf,"PREV_FRAME: layerCount:%2d mdpCount:%2d \
+ cacheCount:%2d \n", mCachedFrame.layerCount,
+ mCachedFrame.mdpCount, mCachedFrame.cacheCount);
+ dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d \
+ fbCount:%2d \n", mCurrentFrame.layerCount,
+ mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
+ dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
+ (mCurrentFrame.needsRedraw? "YES" : "NO"),
+ mCurrentFrame.mdpCount, sMaxPipesPerMixer);
+ dumpsys_log(buf," --------------------------------------------- \n");
+ dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
+ dumpsys_log(buf," --------------------------------------------- \n");
+ for(int index = 0; index < mCurrentFrame.layerCount; index++ )
+ dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
+ index,
+ (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
+ mCurrentFrame.layerToMDP[index],
+ (mCurrentFrame.isFBComposed[index] ?
+ (mCurrentFrame.needsRedraw ? "GLES" : "CACHE") : "MDP"),
+ (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
+ mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
+ dumpsys_log(buf,"\n");
}
bool MDPComp::init(hwc_context_t *ctx) {
@@ -67,8 +91,8 @@
sEnabled = false;
if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
- (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
sEnabled = true;
}
@@ -78,6 +102,12 @@
sDebugLogs = true;
}
+ sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
+ if(property_get("debug.mdpcomp.maxpermixer", property, NULL) > 0) {
+ if(atoi(property) != 0)
+ sMaxPipesPerMixer = true;
+ }
+
unsigned long idle_timeout = DEFAULT_IDLE_TIME;
if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
if(atoi(property) != 0)
@@ -88,7 +118,7 @@
idleInvalidator = IdleInvalidator::getInstance();
if(idleInvalidator == NULL) {
- ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
+ ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
} else {
idleInvalidator->init(timeout_handler, ctx, idle_timeout);
}
@@ -113,33 +143,24 @@
}
void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- const int dpy = HWC_DISPLAY_PRIMARY;
- LayerProp *layerProp = ctx->layerProp[dpy];
+ hwc_display_contents_1_t* list) {
+ LayerProp *layerProp = ctx->layerProp[mDpy];
- for(int index = 0; index < ctx->listStats[dpy].numAppLayers; index++ ) {
+ for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
hwc_layer_1_t* layer = &(list->hwLayers[index]);
- layerProp[index].mFlags |= HWC_MDPCOMP;
- layer->compositionType = HWC_OVERLAY;
- layer->hints |= HWC_HINT_CLEAR_FB;
- }
-}
-
-void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx,
- hwc_display_contents_1_t* list) {
- const int dpy = HWC_DISPLAY_PRIMARY;
- LayerProp *layerProp = ctx->layerProp[dpy];
-
- for (int index = 0 ;
- index < ctx->listStats[dpy].numAppLayers; index++) {
- if(layerProp[index].mFlags & HWC_MDPCOMP) {
- layerProp[index].mFlags &= ~HWC_MDPCOMP;
- }
-
- if(list->hwLayers[index].compositionType == HWC_OVERLAY) {
- list->hwLayers[index].compositionType = HWC_FRAMEBUFFER;
+ if(!mCurrentFrame.isFBComposed[index]) {
+ layerProp[index].mFlags |= HWC_MDPCOMP;
+ layer->compositionType = HWC_OVERLAY;
+ layer->hints |= HWC_HINT_CLEAR_FB;
+ mCachedFrame.hnd[index] = NULL;
+ } else {
+ if(!mCurrentFrame.needsRedraw)
+ layer->compositionType = HWC_OVERLAY;
}
}
+ mCachedFrame.mdpCount = mCurrentFrame.mdpCount;
+ mCachedFrame.cacheCount = mCurrentFrame.fbCount;
+ mCachedFrame.layerCount = ctx->listStats[mDpy].numAppLayers;
}
/*
@@ -169,41 +190,58 @@
if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
- strerror(errno));
+ strerror(errno));
return false;
}
ovData.id = ovInfo.id;
if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
- strerror(errno));
+ strerror(errno));
return false;
}
return true;
}
+MDPComp::FrameInfo::FrameInfo() {
+ layerCount = 0;
+ reset();
+}
-void MDPComp::reset(hwc_context_t *ctx,
- hwc_display_contents_1_t* list ) {
- //Reset flags and states
- unsetMDPCompLayerFlags(ctx, list);
- if(mCurrentFrame.pipeLayer) {
- for(int i = 0 ; i < mCurrentFrame.count; i++ ) {
- if(mCurrentFrame.pipeLayer[i].pipeInfo) {
- delete mCurrentFrame.pipeLayer[i].pipeInfo;
- mCurrentFrame.pipeLayer[i].pipeInfo = NULL;
- //We dont own the rotator
- mCurrentFrame.pipeLayer[i].rot = NULL;
- }
+void MDPComp::FrameInfo::reset() {
+
+ for(int i = 0 ; i < MAX_PIPES_PER_MIXER && layerCount; i++ ) {
+ if(mdpToLayer[i].pipeInfo) {
+ delete mdpToLayer[i].pipeInfo;
+ mdpToLayer[i].pipeInfo = NULL;
+ //We dont own the rotator
+ mdpToLayer[i].rot = NULL;
}
- free(mCurrentFrame.pipeLayer);
- mCurrentFrame.pipeLayer = NULL;
}
- mCurrentFrame.count = 0;
+
+ memset(&mdpToLayer, 0, sizeof(mdpToLayer));
+ memset(&layerToMDP, -1, sizeof(layerToMDP));
+ memset(&isFBComposed, 0, sizeof(isFBComposed));
+
+ layerCount = 0;
+ mdpCount = 0;
+ fbCount = 0;
+ needsRedraw = false;
+ fbZ = 0;
+}
+
+MDPComp::LayerCache::LayerCache() {
+ reset();
+}
+
+void MDPComp::LayerCache::reset() {
+ memset(&hnd, 0, sizeof(buffer_handle_t));
+ mdpCount = 0;
+ cacheCount = 0;
+ layerCount = 0;
}
bool MDPComp::isWidthValid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
- const int dpy = HWC_DISPLAY_PRIMARY;
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
@@ -211,8 +249,8 @@
return false;
}
- int hw_w = ctx->dpyAttr[dpy].xres;
- int hw_h = ctx->dpyAttr[dpy].yres;
+ int hw_w = ctx->dpyAttr[mDpy].xres;
+ int hw_h = ctx->dpyAttr[mDpy].yres;
hwc_rect_t sourceCrop = layer->sourceCrop;
hwc_rect_t displayFrame = layer->displayFrame;
@@ -226,98 +264,107 @@
int dst_h = dst.bottom - dst.top;
if(dst.left < 0 || dst.top < 0 || dst.right > hw_w || dst.bottom > hw_h) {
- hwc_rect_t scissor = {0, 0, hw_w, hw_h };
- qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
- crop_w = crop.right - crop.left;
- crop_h = crop.bottom - crop.top;
+ hwc_rect_t scissor = {0, 0, hw_w, hw_h };
+ qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
+ crop_w = crop.right - crop.left;
+ crop_h = crop.bottom - crop.top;
}
- //Workaround for MDP HW limitation in DSI command mode panels where
- //FPS will not go beyond 30 if buffers on RGB pipes are of width < 5
+ /* Workaround for MDP HW limitation in DSI command mode panels where
+ * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
+ * less than 5 pixels
+ * */
- if(crop_w < 5)
+ if((crop_w < 5)||(crop_h < 5))
return false;
return true;
}
ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type) {
- const int dpy = HWC_DISPLAY_PRIMARY;
overlay::Overlay& ov = *ctx->mOverlay;
ovutils::eDest mdp_pipe = ovutils::OV_INVALID;
switch(type) {
- case MDPCOMP_OV_DMA:
- mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, dpy);
- if(mdp_pipe != ovutils::OV_INVALID) {
- ctx->mDMAInUse = true;
- return mdp_pipe;
- }
- case MDPCOMP_OV_ANY:
- case MDPCOMP_OV_RGB:
- mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy);
- if(mdp_pipe != ovutils::OV_INVALID) {
- return mdp_pipe;
- }
+ case MDPCOMP_OV_DMA:
+ mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, mDpy);
+ if(mdp_pipe != ovutils::OV_INVALID) {
+ ctx->mDMAInUse = true;
+ return mdp_pipe;
+ }
+ case MDPCOMP_OV_ANY:
+ case MDPCOMP_OV_RGB:
+ mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
+ if(mdp_pipe != ovutils::OV_INVALID) {
+ return mdp_pipe;
+ }
- if(type == MDPCOMP_OV_RGB) {
- //Requested only for RGB pipe
- break;
- }
- case MDPCOMP_OV_VG:
- return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy);
- default:
- ALOGE("%s: Invalid pipe type",__FUNCTION__);
- return ovutils::OV_INVALID;
+ if(type == MDPCOMP_OV_RGB) {
+ //Requested only for RGB pipe
+ break;
+ }
+ case MDPCOMP_OV_VG:
+ return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy);
+ default:
+ ALOGE("%s: Invalid pipe type",__FUNCTION__);
+ return ovutils::OV_INVALID;
};
return ovutils::OV_INVALID;
}
-bool MDPComp::isDoable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- //Number of layers
- const int dpy = HWC_DISPLAY_PRIMARY;
- int numAppLayers = ctx->listStats[dpy].numAppLayers;
- int numDMAPipes = qdutils::MDPVersion::getInstance().getDMAPipes();
+bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- overlay::Overlay& ov = *ctx->mOverlay;
- int availablePipes = ov.availablePipes(dpy);
-
- if(ctx->mNeedsRotator)
- availablePipes -= numDMAPipes;
-
- if(numAppLayers < 1 || numAppLayers > MAX_PIPES_PER_MIXER ||
- pipesNeeded(ctx, list) > availablePipes) {
- ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
+ if(!isEnabled()) {
+ ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
return false;
}
if(ctx->mExtDispConfiguring) {
ALOGD_IF( isDebug(),"%s: External Display connection is pending",
- __FUNCTION__);
+ __FUNCTION__);
return false;
}
- if(isSecuring(ctx)) {
- ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
- return false;
- }
-
- if(ctx->mSecureMode)
- return false;
-
- //Check for skip layers
- if(isSkipPresent(ctx, dpy)) {
- ALOGD_IF(isDebug(), "%s: Skip layers are present",__FUNCTION__);
- return false;
- }
-
- if(ctx->listStats[dpy].needsAlphaScale
- && ctx->mMDP.version < qdutils::MDSS_V5) {
+ if(ctx->listStats[mDpy].needsAlphaScale
+ && ctx->mMDP.version < qdutils::MDSS_V5) {
ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
return false;
}
+ return true;
+}
+
+/* Checks for conditions where all the layers marked for MDP comp cannot be
+ * bypassed. On such conditions we try to bypass atleast YUV layers */
+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);
+
+ if(mDpy > HWC_DISPLAY_PRIMARY){
+ ALOGD_IF(isDebug(), "%s: Cannot support External display(s)",
+ __FUNCTION__);
+ 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;
@@ -325,11 +372,6 @@
return false;
}
- if(ctx->mNeedsRotator && ctx->mDMAInUse) {
- ALOGD_IF(isDebug(), "%s: DMA not available for Rotator",__FUNCTION__);
- return false;
- }
-
//MDP composition is not efficient if layer needs rotator.
for(int i = 0; i < numAppLayers; ++i) {
// As MDP h/w supports flip operation, use MDP comp only for
@@ -350,65 +392,258 @@
return true;
}
-bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
- const int dpy = HWC_DISPLAY_PRIMARY;
- if(!ctx) {
- ALOGE("%s: invalid context", __FUNCTION__);
- return -1;
- }
+/* Checks for conditions where YUV layers cannot be bypassed */
+bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
- ctx->mDMAInUse = false;
- if(!allocLayerPipes(ctx, list, mCurrentFrame)) {
- ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__);
+ if(isSkipLayer(layer)) {
+ ALOGE("%s: Unable to bypass skipped YUV", __FUNCTION__);
return false;
}
- for (int index = 0 ; index < mCurrentFrame.count; index++) {
- hwc_layer_1_t* layer = &list->hwLayers[index];
- if(configure(ctx, layer, mCurrentFrame.pipeLayer[index]) != 0 ) {
- ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
- layer %d",__FUNCTION__, index);
+ if(ctx->mNeedsRotator && ctx->mDMAInUse) {
+ ALOGE("%s: No DMA for Rotator",__FUNCTION__);
+ return false;
+ }
+
+ if(isSecuring(ctx, layer)) {
+ ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
+ 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) {
+ 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;
+ int dHeight = dst.bottom - dst.top;
+
+ if((cWidth/dWidth) > 4 || (cHeight/dHeight) > 4)
return false;
- }
}
return true;
}
-bool MDPComp::prepare(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- if(!isEnabled()) {
- ALOGE_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
- return false;
+void MDPComp::batchLayers() {
+ /* Idea is to keep as many contiguous non-updating(cached) layers in FB and
+ * send rest of them through MDP. NEVER mark an updating layer for caching.
+ * But cached ones can be marked for MDP*/
+
+ int maxBatchStart = -1;
+ int maxBatchCount = 0;
+
+ /* All or Nothing is cached. No batching needed */
+ if(!mCurrentFrame.fbCount ||
+ (mCurrentFrame.fbCount == mCurrentFrame.layerCount))
+ return;
+
+ /* Search for max number of contiguous (cached) layers */
+ int i = 0;
+ while (i < mCurrentFrame.layerCount) {
+ int count = 0;
+ while(mCurrentFrame.isFBComposed[i] && i < mCurrentFrame.layerCount) {
+ count++; i++;
+ }
+ if(count > maxBatchCount) {
+ maxBatchCount = count;
+ maxBatchStart = i - count;
+ }
+ if(i < mCurrentFrame.layerCount) i++;
}
+ /* reset rest of the layers for MDP comp */
+ for(int i = 0; i < mCurrentFrame.layerCount; i++) {
+ if(i != maxBatchStart){
+ mCurrentFrame.isFBComposed[i] = false;
+ } else {
+ i += maxBatchCount;
+ }
+ }
+
+ mCurrentFrame.fbCount = maxBatchCount;
+
+ ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
+ mCurrentFrame.fbCount);
+}
+void MDPComp::updateLayerCache(hwc_context_t* ctx,
+ hwc_display_contents_1_t* list) {
+
+ 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 {
+ mCachedFrame.hnd[i] = list->hwLayers[i].handle;
+ }
+ }
+ mCurrentFrame.fbCount = numCacheableLayers;
+ ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__, numCacheableLayers);
+}
+
+int MDPComp::getAvailablePipes(hwc_context_t* ctx) {
+ int numDMAPipes = qdutils::MDPVersion::getInstance().getDMAPipes();
overlay::Overlay& ov = *ctx->mOverlay;
- bool isMDPCompUsed = true;
+
+ int numAvailable = ov.availablePipes(mDpy);
+
+ //Reserve DMA for rotator
+ if(ctx->mNeedsRotator)
+ numAvailable -= numDMAPipes;
+
+ //Reserve pipe(s)for FB
+ if(mCurrentFrame.fbCount)
+ numAvailable -= pipesForFB();
+
+ 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;
+ for(int index = 0;index < nYuvCount; index++){
+ int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
+ hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
+
+ if(!isYUVDoable(ctx, layer)) {
+ if(!mCurrentFrame.isFBComposed[nYuvIndex]) {
+ mCurrentFrame.isFBComposed[nYuvIndex] = true;
+ mCurrentFrame.fbCount++;
+ }
+ } else {
+ if(mCurrentFrame.isFBComposed[nYuvIndex]) {
+ mCurrentFrame.isFBComposed[nYuvIndex] = false;
+ 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;
+ ctx->mDMAInUse = false;
+
+ if(!allocLayerPipes(ctx, list)) {
+ ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
+ goto fn_exit;
+ }
+
+ for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
+ index++) {
+ if(!mCurrentFrame.isFBComposed[index]) {
+
+ int mdpIndex = mCurrentFrame.layerToMDP[index];
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+
+ MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+ cur_pipe->zOrder = mdpNextZOrder++;
+
+ if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
+ ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
+ layer %d",__FUNCTION__, index);
+ goto fn_exit;
+ }
+ } else if(fbZOrder < 0) {
+ fbZOrder = mdpNextZOrder++;
+ };
+ }
+
+ return fbZOrder;
+
+ fn_exit:
+ //Complete fallback to FB
+ resetFrameForFB(ctx, list);
+ return 0;
+}
+
+int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
//reset old data
- reset(ctx, list);
+ mCurrentFrame.reset();
- bool doable = isDoable(ctx, list);
- if(doable) {
- if(setup(ctx, list)) {
- setMDPCompLayerFlags(ctx, list);
- } else {
- ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
- isMDPCompUsed = false;
+ if(!isFrameDoable(ctx)) {
+ ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
+ __FUNCTION__);
+ 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)){
+ //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);
+ }
+
+ 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++;
+ }
}
- } else {
- ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
- doable);
- isMDPCompUsed = false;
+ //Acquire and Program MDP pipes
+ mCurrentFrame.fbZ = programMDP(ctx, list);
}
- //Reset states
- if(!isMDPCompUsed) {
- //Reset current frame
- reset(ctx, list);
+ /* Any change in composition types needs an FB refresh*/
+ if(mCurrentFrame.fbCount &&
+ ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) ||
+ (mCurrentFrame.fbCount != mCachedFrame.cacheCount) ||
+ !mCurrentFrame.mdpCount)) {
+ mCurrentFrame.needsRedraw = true;
}
- mState = isMDPCompUsed ? MDPCOMP_ON : MDPCOMP_OFF;
- return isMDPCompUsed;
+ //UpdateLayerFlags
+ setMDPCompLayerFlags(ctx, list);
+
+ if(isDebug()) {
+ android::String8 sDump("");
+ dump(sDump);
+ ALOGE("%s",sDump.string());
+ }
+
+ return mCurrentFrame.fbZ;
}
//=============MDPCompLowRes===================================================
@@ -417,64 +652,66 @@
* Configures pipe(s) for MDP composition
*/
int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& pipeLayerPair) {
- const int dpy = HWC_DISPLAY_PRIMARY;
+ PipeLayerPair& PipeLayerPair) {
MdpPipeInfoLowRes& mdp_info =
- *(static_cast<MdpPipeInfoLowRes*>(pipeLayerPair.pipeInfo));
+ *(static_cast<MdpPipeInfoLowRes*>(PipeLayerPair.pipeInfo));
eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
eIsFg isFg = IS_FG_OFF;
eDest dest = mdp_info.index;
- return configureLowRes(ctx, layer, dpy, mdpFlags, zOrder, isFg, dest,
- &pipeLayerPair.rot);
+ 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,
+ &PipeLayerPair.rot);
}
int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- const int dpy = HWC_DISPLAY_PRIMARY;
- return ctx->listStats[dpy].numAppLayers;
+ hwc_display_contents_1_t* list) {
+ return mCurrentFrame.mdpCount;
}
bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
- hwc_display_contents_1_t* list,
- FrameInfo& currentFrame) {
- const int dpy = HWC_DISPLAY_PRIMARY;
- overlay::Overlay& ov = *ctx->mOverlay;
- int layer_count = ctx->listStats[dpy].numAppLayers;
+ hwc_display_contents_1_t* list) {
+ if(isYuvPresent(ctx, mDpy)) {
+ int nYuvCount = ctx->listStats[mDpy].yuvCount;
- currentFrame.count = layer_count;
- currentFrame.pipeLayer = (PipeLayerPair*)
- malloc(sizeof(PipeLayerPair) * currentFrame.count);
+ for(int index = 0; index < nYuvCount ; index ++) {
+ int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
- if(isYuvPresent(ctx, dpy)) {
- int nYuvCount = ctx->listStats[dpy].yuvCount;
+ if(mCurrentFrame.isFBComposed[nYuvIndex])
+ continue;
- for(int index = 0; index < nYuvCount; index ++) {
- int nYuvIndex = ctx->listStats[dpy].yuvIndices[index];
hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
- PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
+
+ int mdpIndex = mCurrentFrame.layerToMDP[nYuvIndex];
+
+ PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
info.pipeInfo = new MdpPipeInfoLowRes;
info.rot = NULL;
MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
+
pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
if(pipe_info.index == ovutils::OV_INVALID) {
ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos",
- __FUNCTION__);
+ __FUNCTION__);
return false;
}
- pipe_info.zOrder = nYuvIndex;
}
}
- for(int index = 0 ; index < layer_count ; index++ ) {
+ for(int index = 0 ; index < mCurrentFrame.layerCount; index++ ) {
+ if(mCurrentFrame.isFBComposed[index]) continue;
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(isYuvBuffer(hnd))
continue;
- PipeLayerPair& info = currentFrame.pipeLayer[index];
+ int mdpIndex = mCurrentFrame.layerToMDP[index];
+
+ PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
info.pipeInfo = new MdpPipeInfoLowRes;
info.rot = NULL;
MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
@@ -482,7 +719,7 @@
ePipeType type = MDPCOMP_OV_ANY;
if(!qhwc::needsScaling(layer) && !ctx->mNeedsRotator
- && ctx->mMDP.version >= qdutils::MDSS_V5) {
+ && ctx->mMDP.version >= qdutils::MDSS_V5) {
type = MDPCOMP_OV_DMA;
}
@@ -491,14 +728,13 @@
ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
return false;
}
- pipe_info.zOrder = index;
}
return true;
}
bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
- if(!isEnabled() || !isUsed()) {
+ if(!isEnabled()) {
ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
return true;
}
@@ -509,16 +745,17 @@
}
/* reset Invalidator */
- if(idleInvalidator)
+ if(idleInvalidator && mCurrentFrame.mdpCount)
idleInvalidator->markForSleep();
- const int dpy = HWC_DISPLAY_PRIMARY;
overlay::Overlay& ov = *ctx->mOverlay;
- LayerProp *layerProp = ctx->layerProp[dpy];
+ LayerProp *layerProp = ctx->layerProp[mDpy];
- int numHwLayers = ctx->listStats[dpy].numAppLayers;
- for(int i = 0; i < numHwLayers; i++ )
+ int numHwLayers = ctx->listStats[mDpy].numAppLayers;
+ for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
{
+ if(mCurrentFrame.isFBComposed[i]) continue;
+
hwc_layer_1_t *layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
@@ -526,8 +763,10 @@
return false;
}
+ int mdpIndex = mCurrentFrame.layerToMDP[i];
+
MdpPipeInfoLowRes& pipe_info =
- *(MdpPipeInfoLowRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
+ *(MdpPipeInfoLowRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
ovutils::eDest dest = pipe_info.index;
if(dest == ovutils::OV_INVALID) {
ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
@@ -539,12 +778,12 @@
}
ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer,
- hnd, dest );
+ using pipe: %d", __FUNCTION__, layer,
+ hnd, dest );
int fd = hnd->fd;
uint32_t offset = hnd->offset;
- Rotator *rot = mCurrentFrame.pipeLayer[i].rot;
+ Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
if(rot) {
if(!rot->queueBuffer(fd, offset))
return false;
@@ -565,77 +804,70 @@
//=============MDPCompHighRes===================================================
int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- const int dpy = HWC_DISPLAY_PRIMARY;
- int numAppLayers = ctx->listStats[dpy].numAppLayers;
+ hwc_display_contents_1_t* list) {
int pipesNeeded = 0;
+ int hw_w = ctx->dpyAttr[mDpy].xres;
- int hw_w = ctx->dpyAttr[dpy].xres;
-
- for(int i = 0; i < numAppLayers; ++i) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- hwc_rect_t dst = layer->displayFrame;
- if(dst.left > hw_w/2) {
- pipesNeeded++;
- } else if(dst.right <= hw_w/2) {
- pipesNeeded++;
- } else {
- pipesNeeded += 2;
- }
+ for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
+ if(!mCurrentFrame.isFBComposed[i]) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ hwc_rect_t dst = layer->displayFrame;
+ if(dst.left > hw_w/2) {
+ pipesNeeded++;
+ } else if(dst.right <= hw_w/2) {
+ pipesNeeded++;
+ } else {
+ pipesNeeded += 2;
+ }
+ }
}
return pipesNeeded;
}
bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoHighRes& pipe_info, ePipeType type) {
- const int dpy = HWC_DISPLAY_PRIMARY;
- int hw_w = ctx->dpyAttr[dpy].xres;
+ MdpPipeInfoHighRes& pipe_info,
+ ePipeType type) {
+ int hw_w = ctx->dpyAttr[mDpy].xres;
- hwc_rect_t dst = layer->displayFrame;
- if(dst.left > hw_w/2) {
- pipe_info.lIndex = ovutils::OV_INVALID;
- pipe_info.rIndex = getMdpPipe(ctx, type);
- if(pipe_info.rIndex == ovutils::OV_INVALID)
- return false;
- } else if (dst.right <= hw_w/2) {
- pipe_info.rIndex = ovutils::OV_INVALID;
- pipe_info.lIndex = getMdpPipe(ctx, type);
- if(pipe_info.lIndex == ovutils::OV_INVALID)
- return false;
- } else {
- pipe_info.rIndex = getMdpPipe(ctx, type);
- pipe_info.lIndex = getMdpPipe(ctx, type);
- if(pipe_info.rIndex == ovutils::OV_INVALID ||
- pipe_info.lIndex == ovutils::OV_INVALID)
- return false;
- }
- return true;
+ hwc_rect_t dst = layer->displayFrame;
+ if(dst.left > hw_w/2) {
+ pipe_info.lIndex = ovutils::OV_INVALID;
+ pipe_info.rIndex = getMdpPipe(ctx, type);
+ if(pipe_info.rIndex == ovutils::OV_INVALID)
+ return false;
+ } else if (dst.right <= hw_w/2) {
+ pipe_info.rIndex = ovutils::OV_INVALID;
+ pipe_info.lIndex = getMdpPipe(ctx, type);
+ if(pipe_info.lIndex == ovutils::OV_INVALID)
+ return false;
+ } else {
+ pipe_info.rIndex = getMdpPipe(ctx, type);
+ pipe_info.lIndex = getMdpPipe(ctx, type);
+ if(pipe_info.rIndex == ovutils::OV_INVALID ||
+ pipe_info.lIndex == ovutils::OV_INVALID)
+ return false;
+ }
+ return true;
}
bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx,
- hwc_display_contents_1_t* list,
- FrameInfo& currentFrame) {
- const int dpy = HWC_DISPLAY_PRIMARY;
+ hwc_display_contents_1_t* list) {
overlay::Overlay& ov = *ctx->mOverlay;
- int layer_count = ctx->listStats[dpy].numAppLayers;
+ int layer_count = ctx->listStats[mDpy].numAppLayers;
- currentFrame.count = layer_count;
- currentFrame.pipeLayer = (PipeLayerPair*)
- malloc(sizeof(PipeLayerPair) * currentFrame.count);
-
- if(isYuvPresent(ctx, dpy)) {
- int nYuvCount = ctx->listStats[dpy].yuvCount;
+ if(isYuvPresent(ctx, mDpy)) {
+ int nYuvCount = ctx->listStats[mDpy].yuvCount;
for(int index = 0; index < nYuvCount; index ++) {
- int nYuvIndex = ctx->listStats[dpy].yuvIndices[index];
+ int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
- PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
+ PipeLayerPair& info = mCurrentFrame.mdpToLayer[nYuvIndex];
info.pipeInfo = new MdpPipeInfoHighRes;
info.rot = NULL;
MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
if(!acquireMDPPipes(ctx, layer, pipe_info,MDPCOMP_OV_VG)) {
ALOGD_IF(isDebug(),"%s: Unable to get pipe for videos",
- __FUNCTION__);
+ __FUNCTION__);
//TODO: windback pipebook data on fail
return false;
}
@@ -650,7 +882,7 @@
if(isYuvBuffer(hnd))
continue;
- PipeLayerPair& info = currentFrame.pipeLayer[index];
+ PipeLayerPair& info = mCurrentFrame.mdpToLayer[index];
info.pipeInfo = new MdpPipeInfoHighRes;
info.rot = NULL;
MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
@@ -658,7 +890,7 @@
ePipeType type = MDPCOMP_OV_ANY;
if(!qhwc::needsScaling(layer) && !ctx->mNeedsRotator
- && ctx->mMDP.version >= qdutils::MDSS_V5)
+ && ctx->mMDP.version >= qdutils::MDSS_V5)
type = MDPCOMP_OV_DMA;
if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
@@ -674,22 +906,25 @@
* Configures pipe(s) for MDP composition
*/
int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
- PipeLayerPair& pipeLayerPair) {
- const int dpy = HWC_DISPLAY_PRIMARY;
+ PipeLayerPair& PipeLayerPair) {
MdpPipeInfoHighRes& mdp_info =
- *(static_cast<MdpPipeInfoHighRes*>(pipeLayerPair.pipeInfo));
+ *(static_cast<MdpPipeInfoHighRes*>(PipeLayerPair.pipeInfo));
eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
eIsFg isFg = IS_FG_OFF;
eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
eDest lDest = mdp_info.lIndex;
eDest rDest = mdp_info.rIndex;
- return configureHighRes(ctx, layer, dpy, mdpFlagsL, zOrder, isFg, lDest,
- rDest, &pipeLayerPair.rot);
+
+ 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,
+ rDest, &PipeLayerPair.rot);
}
bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
- if(!isEnabled() || !isUsed()) {
+ if(!isEnabled()) {
ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
return true;
}
@@ -700,16 +935,17 @@
}
/* reset Invalidator */
- if(idleInvalidator)
+ if(idleInvalidator && mCurrentFrame.mdpCount)
idleInvalidator->markForSleep();
- const int dpy = HWC_DISPLAY_PRIMARY;
overlay::Overlay& ov = *ctx->mOverlay;
- LayerProp *layerProp = ctx->layerProp[dpy];
+ LayerProp *layerProp = ctx->layerProp[mDpy];
- int numHwLayers = ctx->listStats[dpy].numAppLayers;
- for(int i = 0; i < numHwLayers; i++ )
+ int numHwLayers = ctx->listStats[mDpy].numAppLayers;
+ for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
{
+ if(mCurrentFrame.isFBComposed[i]) continue;
+
hwc_layer_1_t *layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
@@ -721,12 +957,15 @@
continue;
}
+ int mdpIndex = mCurrentFrame.layerToMDP[i];
+
MdpPipeInfoHighRes& pipe_info =
- *(MdpPipeInfoHighRes*)mCurrentFrame.pipeLayer[i].pipeInfo;
- Rotator *rot = mCurrentFrame.pipeLayer[i].rot;
+ *(MdpPipeInfoHighRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+ Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
ovutils::eDest indexL = pipe_info.lIndex;
ovutils::eDest indexR = pipe_info.rIndex;
+
int fd = hnd->fd;
int offset = hnd->offset;
@@ -740,7 +979,7 @@
if(indexL != ovutils::OV_INVALID) {
ovutils::eDest destL = (ovutils::eDest)indexL;
ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer, hnd, indexL );
+ using pipe: %d", __FUNCTION__, layer, hnd, indexL );
if (!ov.queueBuffer(fd, offset, destL)) {
ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__);
return false;
@@ -751,7 +990,7 @@
if(indexR != ovutils::OV_INVALID) {
ovutils::eDest destR = (ovutils::eDest)indexR;
ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer, hnd, indexR );
+ using pipe: %d", __FUNCTION__, layer, hnd, indexR );
if (!ov.queueBuffer(fd, offset, destR)) {
ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__);
return false;