Home | History | Annotate | Download | only in libhwcomposer
      1 /*
      2  * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
      3  * Not a Contribution, Apache license notifications and license are retained
      4  * for attribution purposes only.
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 
     19 #include <math.h>
     20 #include "hwc_mdpcomp.h"
     21 #include <sys/ioctl.h>
     22 #include "qdMetaData.h"
     23 #include "mdp_version.h"
     24 #include "hwc_fbupdate.h"
     25 #include "hwc_ad.h"
     26 #include <overlayRotator.h>
     27 
     28 using namespace overlay;
     29 using namespace qdutils;
     30 using namespace overlay::utils;
     31 namespace ovutils = overlay::utils;
     32 
     33 namespace qhwc {
     34 
     35 //==============MDPComp========================================================
     36 
     37 IdleInvalidator *MDPComp::idleInvalidator = NULL;
     38 bool MDPComp::sIdleFallBack = false;
     39 bool MDPComp::sDebugLogs = false;
     40 bool MDPComp::sEnabled = false;
     41 bool MDPComp::sEnableMixedMode = true;
     42 int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
     43 
     44 MDPComp* MDPComp::getObject(const int& width, const int& rightSplit,
     45         const int& dpy) {
     46     if(width > MAX_DISPLAY_DIM || rightSplit) {
     47         return new MDPCompHighRes(dpy);
     48     }
     49     return new MDPCompLowRes(dpy);
     50 }
     51 
     52 MDPComp::MDPComp(int dpy):mDpy(dpy){};
     53 
     54 void MDPComp::dump(android::String8& buf)
     55 {
     56     if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
     57         return;
     58 
     59     dumpsys_log(buf,"HWC Map for Dpy: %s \n",
     60                 (mDpy == 0) ? "\"PRIMARY\"" :
     61                 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
     62     dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
     63                 "fbCount:%2d \n", mCurrentFrame.layerCount,
     64                 mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
     65     dumpsys_log(buf,"needsFBRedraw:%3s  pipesUsed:%2d  MaxPipesPerMixer: %d \n",
     66                 (mCurrentFrame.needsRedraw? "YES" : "NO"),
     67                 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
     68     dumpsys_log(buf," ---------------------------------------------  \n");
     69     dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype  |  Z  \n");
     70     dumpsys_log(buf," ---------------------------------------------  \n");
     71     for(int index = 0; index < mCurrentFrame.layerCount; index++ )
     72         dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
     73                     index,
     74                     (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
     75                     mCurrentFrame.layerToMDP[index],
     76                     (mCurrentFrame.isFBComposed[index] ?
     77                      (mCurrentFrame.needsRedraw ? "GLES" : "CACHE") : "MDP"),
     78                     (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
     79     mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
     80     dumpsys_log(buf,"\n");
     81 }
     82 
     83 bool MDPComp::init(hwc_context_t *ctx) {
     84 
     85     if(!ctx) {
     86         ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
     87         return false;
     88     }
     89 
     90     char property[PROPERTY_VALUE_MAX];
     91 
     92     sEnabled = false;
     93     if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
     94        (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
     95         (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
     96         sEnabled = true;
     97     }
     98 
     99     sEnableMixedMode = true;
    100     if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
    101        (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
    102         (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
    103         sEnableMixedMode = false;
    104     }
    105 
    106     sDebugLogs = false;
    107     if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
    108         if(atoi(property) != 0)
    109             sDebugLogs = true;
    110     }
    111 
    112     sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
    113     if(property_get("debug.mdpcomp.maxpermixer", property, "-1") > 0) {
    114         int val = atoi(property);
    115         if(val >= 0)
    116             sMaxPipesPerMixer = min(val, MAX_PIPES_PER_MIXER);
    117     }
    118 
    119     if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
    120         // Idle invalidation is not necessary on command mode panels
    121         long idle_timeout = DEFAULT_IDLE_TIME;
    122         if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
    123             if(atoi(property) != 0)
    124                 idle_timeout = atoi(property);
    125         }
    126 
    127         //create Idle Invalidator only when not disabled through property
    128         if(idle_timeout != -1)
    129             idleInvalidator = IdleInvalidator::getInstance();
    130 
    131         if(idleInvalidator == NULL) {
    132             ALOGE("%s: failed to instantiate idleInvalidator object",
    133                   __FUNCTION__);
    134         } else {
    135             idleInvalidator->init(timeout_handler, ctx, idle_timeout);
    136         }
    137     }
    138     return true;
    139 }
    140 
    141 void MDPComp::reset(const int& numLayers, hwc_display_contents_1_t* list) {
    142     mCurrentFrame.reset(numLayers);
    143     mCachedFrame.cacheAll(list);
    144     mCachedFrame.updateCounts(mCurrentFrame);
    145 }
    146 
    147 void MDPComp::timeout_handler(void *udata) {
    148     struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
    149 
    150     if(!ctx) {
    151         ALOGE("%s: received empty data in timer callback", __FUNCTION__);
    152         return;
    153     }
    154 
    155     if(!ctx->proc) {
    156         ALOGE("%s: HWC proc not registered", __FUNCTION__);
    157         return;
    158     }
    159     sIdleFallBack = true;
    160     /* Trigger SF to redraw the current frame */
    161     ctx->proc->invalidate(ctx->proc);
    162 }
    163 
    164 void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
    165                                    hwc_display_contents_1_t* list) {
    166     LayerProp *layerProp = ctx->layerProp[mDpy];
    167 
    168     for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
    169         hwc_layer_1_t* layer = &(list->hwLayers[index]);
    170         if(!mCurrentFrame.isFBComposed[index]) {
    171             layerProp[index].mFlags |= HWC_MDPCOMP;
    172             layer->compositionType = HWC_OVERLAY;
    173             layer->hints |= HWC_HINT_CLEAR_FB;
    174         } else {
    175             if(!mCurrentFrame.needsRedraw)
    176                 layer->compositionType = HWC_OVERLAY;
    177         }
    178     }
    179 }
    180 
    181 MDPComp::FrameInfo::FrameInfo() {
    182     memset(&mdpToLayer, 0, sizeof(mdpToLayer));
    183     reset(0);
    184 }
    185 
    186 void MDPComp::FrameInfo::reset(const int& numLayers) {
    187     for(int i = 0 ; i < MAX_PIPES_PER_MIXER; i++ ) {
    188         if(mdpToLayer[i].pipeInfo) {
    189             delete mdpToLayer[i].pipeInfo;
    190             mdpToLayer[i].pipeInfo = NULL;
    191             //We dont own the rotator
    192             mdpToLayer[i].rot = NULL;
    193         }
    194     }
    195 
    196     memset(&mdpToLayer, 0, sizeof(mdpToLayer));
    197     memset(&layerToMDP, -1, sizeof(layerToMDP));
    198     memset(&isFBComposed, 1, sizeof(isFBComposed));
    199 
    200     layerCount = numLayers;
    201     fbCount = numLayers;
    202     mdpCount = 0;
    203     needsRedraw = true;
    204     fbZ = 0;
    205 }
    206 
    207 void MDPComp::FrameInfo::map() {
    208     // populate layer and MDP maps
    209     int mdpIdx = 0;
    210     for(int idx = 0; idx < layerCount; idx++) {
    211         if(!isFBComposed[idx]) {
    212             mdpToLayer[mdpIdx].listIndex = idx;
    213             layerToMDP[idx] = mdpIdx++;
    214         }
    215     }
    216 }
    217 
    218 MDPComp::LayerCache::LayerCache() {
    219     reset();
    220 }
    221 
    222 void MDPComp::LayerCache::reset() {
    223     memset(&hnd, 0, sizeof(hnd));
    224     mdpCount = 0;
    225     fbCount = 0;
    226     layerCount = 0;
    227     fbZ = -1;
    228 }
    229 
    230 void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
    231     const int numAppLayers = list->numHwLayers - 1;
    232     for(int i = 0; i < numAppLayers; i++) {
    233         hnd[i] = list->hwLayers[i].handle;
    234     }
    235 }
    236 
    237 void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
    238     mdpCount = curFrame.mdpCount;
    239     fbCount = curFrame.fbCount;
    240     layerCount = curFrame.layerCount;
    241     fbZ = curFrame.fbZ;
    242 }
    243 
    244 bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
    245     private_handle_t *hnd = (private_handle_t *)layer->handle;
    246     if((not isYuvBuffer(hnd) and has90Transform(layer)) or
    247         (not isValidDimension(ctx,layer))
    248         //More conditions here, SKIP, sRGB+Blend etc
    249         ) {
    250         return false;
    251     }
    252     return true;
    253 }
    254 
    255 bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
    256     const int dpy = HWC_DISPLAY_PRIMARY;
    257     private_handle_t *hnd = (private_handle_t *)layer->handle;
    258 
    259     if(!hnd) {
    260         ALOGE("%s: layer handle is NULL", __FUNCTION__);
    261         return false;
    262     }
    263 
    264     //XXX: Investigate doing this with pixel phase on MDSS
    265     if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
    266         return false;
    267 
    268     int hw_w = ctx->dpyAttr[mDpy].xres;
    269     int hw_h = ctx->dpyAttr[mDpy].yres;
    270 
    271     hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
    272     hwc_rect_t dst = layer->displayFrame;
    273 
    274     if(dst.left < 0 || dst.top < 0 || dst.right > hw_w || dst.bottom > hw_h) {
    275        hwc_rect_t scissor = {0, 0, hw_w, hw_h };
    276        qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
    277     }
    278 
    279     bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
    280     int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
    281     int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
    282     int dst_w = dst.right - dst.left;
    283     int dst_h = dst.bottom - dst.top;
    284     float w_dscale = ceilf((float)crop_w / (float)dst_w);
    285     float h_dscale = ceilf((float)crop_h / (float)dst_h);
    286 
    287     //Workaround for MDP HW limitation in DSI command mode panels where
    288     //FPS will not go beyond 30 if buffers on RGB pipes are of width < 5
    289 
    290     if((crop_w < 5)||(crop_h < 5))
    291         return false;
    292 
    293     const uint32_t downscale =
    294             qdutils::MDPVersion::getInstance().getMaxMDPDownscale();
    295     if(ctx->mMDP.version >= qdutils::MDSS_V5) {
    296         if(!qdutils::MDPVersion::getInstance().supportsDecimation()) {
    297             if(crop_w > MAX_DISPLAY_DIM || w_dscale > downscale ||
    298                     h_dscale > downscale)
    299                 return false;
    300         } else if(w_dscale > 64 || h_dscale > 64) {
    301             return false;
    302         }
    303     } else { //A-family
    304         if(w_dscale > downscale || h_dscale > downscale)
    305             return false;
    306     }
    307 
    308     return true;
    309 }
    310 
    311 ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type,
    312         int mixer) {
    313     overlay::Overlay& ov = *ctx->mOverlay;
    314     ovutils::eDest mdp_pipe = ovutils::OV_INVALID;
    315 
    316     switch(type) {
    317     case MDPCOMP_OV_DMA:
    318         mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, mDpy, mixer);
    319         if(mdp_pipe != ovutils::OV_INVALID) {
    320             return mdp_pipe;
    321         }
    322     case MDPCOMP_OV_ANY:
    323     case MDPCOMP_OV_RGB:
    324         mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy, mixer);
    325         if(mdp_pipe != ovutils::OV_INVALID) {
    326             return mdp_pipe;
    327         }
    328 
    329         if(type == MDPCOMP_OV_RGB) {
    330             //Requested only for RGB pipe
    331             break;
    332         }
    333     case  MDPCOMP_OV_VG:
    334         return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy, mixer);
    335     default:
    336         ALOGE("%s: Invalid pipe type",__FUNCTION__);
    337         return ovutils::OV_INVALID;
    338     };
    339     return ovutils::OV_INVALID;
    340 }
    341 
    342 bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
    343     bool ret = true;
    344     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    345 
    346     if(!isEnabled()) {
    347         ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
    348         ret = false;
    349     } else if(qdutils::MDPVersion::getInstance().is8x26() &&
    350             ctx->mVideoTransFlag &&
    351             isSecondaryConnected(ctx)) {
    352         //1 Padding round to shift pipes across mixers
    353         ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
    354                 __FUNCTION__);
    355         ret = false;
    356     } else if(isSecondaryConfiguring(ctx)) {
    357         ALOGD_IF( isDebug(),"%s: External Display connection is pending",
    358                   __FUNCTION__);
    359         ret = false;
    360     } else if(ctx->isPaddingRound) {
    361         ctx->isPaddingRound = false;
    362         ALOGD_IF(isDebug(), "%s: padding round",__FUNCTION__);
    363         ret = false;
    364     }
    365     return ret;
    366 }
    367 
    368 /* Checks for conditions where all the layers marked for MDP comp cannot be
    369  * bypassed. On such conditions we try to bypass atleast YUV layers */
    370 bool MDPComp::isFullFrameDoable(hwc_context_t *ctx,
    371                                 hwc_display_contents_1_t* list){
    372 
    373     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    374 
    375     if(sIdleFallBack) {
    376         ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
    377         return false;
    378     }
    379 
    380     if(isSkipPresent(ctx, mDpy)) {
    381         ALOGD_IF(isDebug(),"%s: SKIP present: %d",
    382                 __FUNCTION__,
    383                 isSkipPresent(ctx, mDpy));
    384         return false;
    385     }
    386 
    387     if(ctx->listStats[mDpy].needsAlphaScale
    388        && ctx->mMDP.version < qdutils::MDSS_V5) {
    389         ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
    390         return false;
    391     }
    392 
    393     for(int i = 0; i < numAppLayers; ++i) {
    394         hwc_layer_1_t* layer = &list->hwLayers[i];
    395         private_handle_t *hnd = (private_handle_t *)layer->handle;
    396 
    397         if(isYuvBuffer(hnd) && has90Transform(layer)) {
    398             if(!canUseRotator(ctx, mDpy)) {
    399                 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
    400                         __FUNCTION__, mDpy);
    401                 return false;
    402             }
    403         }
    404 
    405         if(mDpy > HWC_DISPLAY_PRIMARY && isL3SecureBuffer(hnd)) {
    406             return false;
    407         }
    408 
    409         //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
    410         // may not need it if Gfx pre-rotation can handle all flips & rotations
    411         if(qdutils::MDPVersion::getInstance().is8x26() &&
    412                                 (ctx->dpyAttr[mDpy].xres > 1024) &&
    413                                 (layer->transform & HWC_TRANSFORM_FLIP_H) &&
    414                                 (!isYuvBuffer(hnd)))
    415                    return false;
    416     }
    417 
    418     if(ctx->mAD->isDoable()) {
    419         return false;
    420     }
    421 
    422     //If all above hard conditions are met we can do full or partial MDP comp.
    423     bool ret = false;
    424     if(fullMDPComp(ctx, list)) {
    425         ret = true;
    426     } else if(partialMDPComp(ctx, list)) {
    427         ret = true;
    428     }
    429     return ret;
    430 }
    431 
    432 bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    433     //Will benefit presentation / secondary-only layer.
    434     if((mDpy > HWC_DISPLAY_PRIMARY) &&
    435             (list->numHwLayers - 1) > MAX_SEC_LAYERS) {
    436         ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
    437         return false;
    438     }
    439 
    440     /* XXX: There is some flicker currently seen with partial
    441      * MDP composition on the virtual display.
    442      * Disable UI MDP comp on virtual until it is fixed*/
    443 
    444     if(mDpy > HWC_DISPLAY_EXTERNAL) {
    445         return false;
    446     }
    447 
    448     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    449     for(int i = 0; i < numAppLayers; i++) {
    450         hwc_layer_1_t* layer = &list->hwLayers[i];
    451         if(not isSupportedForMDPComp(ctx, layer)) {
    452             ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
    453             return false;
    454         }
    455     }
    456 
    457     //Setup mCurrentFrame
    458     mCurrentFrame.mdpCount = mCurrentFrame.layerCount;
    459     mCurrentFrame.fbCount = 0;
    460     mCurrentFrame.fbZ = -1;
    461     memset(&mCurrentFrame.isFBComposed, 0, sizeof(mCurrentFrame.isFBComposed));
    462 
    463     int mdpCount = mCurrentFrame.mdpCount;
    464     if(mdpCount > sMaxPipesPerMixer) {
    465         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
    466         return false;
    467     }
    468 
    469     if(!arePipesAvailable(ctx, list)) {
    470         return false;
    471     }
    472 
    473     return true;
    474 }
    475 
    476 bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
    477 {
    478     if(!sEnableMixedMode) {
    479         //Mixed mode is disabled. No need to even try caching.
    480         return false;
    481     }
    482 
    483     bool ret = false;
    484     if(isLoadBasedCompDoable(ctx, list)) {
    485         ret = loadBasedComp(ctx, list);
    486     }
    487 
    488     if(!ret) {
    489         ret = cacheBasedComp(ctx, list);
    490     }
    491 
    492     return ret;
    493 }
    494 
    495 bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
    496         hwc_display_contents_1_t* list) {
    497     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    498     mCurrentFrame.reset(numAppLayers);
    499     updateLayerCache(ctx, list);
    500 
    501     //If an MDP marked layer is unsupported cannot do partial MDP Comp
    502     for(int i = 0; i < numAppLayers; i++) {
    503         if(!mCurrentFrame.isFBComposed[i]) {
    504             hwc_layer_1_t* layer = &list->hwLayers[i];
    505             if(not isSupportedForMDPComp(ctx, layer)) {
    506                 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
    507                         __FUNCTION__);
    508                 return false;
    509             }
    510         }
    511     }
    512 
    513     updateYUV(ctx, list);
    514     bool ret = batchLayers(ctx, list); //sets up fbZ also
    515     if(!ret) {
    516         ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
    517         return false;
    518     }
    519 
    520     int mdpCount = mCurrentFrame.mdpCount;
    521 
    522     //Will benefit cases where a video has non-updating background.
    523     if((mDpy > HWC_DISPLAY_PRIMARY) and
    524             (mdpCount > MAX_SEC_LAYERS)) {
    525         ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
    526         return false;
    527     }
    528 
    529     /* XXX: There is some flicker currently seen with partial
    530      * MDP composition on the virtual display.
    531      * Disable UI MDP comp on virtual until it is fixed*/
    532 
    533     if(mDpy > HWC_DISPLAY_EXTERNAL) {
    534         return false;
    535     }
    536 
    537     if(mdpCount > (sMaxPipesPerMixer - 1)) { // -1 since FB is used
    538         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
    539         return false;
    540     }
    541 
    542     if(!arePipesAvailable(ctx, list)) {
    543         return false;
    544     }
    545 
    546     return true;
    547 }
    548 
    549 bool MDPComp::loadBasedComp(hwc_context_t *ctx,
    550         hwc_display_contents_1_t* list) {
    551     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    552     mCurrentFrame.reset(numAppLayers);
    553 
    554     //TODO BatchSize could be optimized further based on available pipes, split
    555     //displays etc.
    556     const int batchSize = numAppLayers - (sMaxPipesPerMixer - 1);
    557     if(batchSize <= 0) {
    558         ALOGD_IF(isDebug(), "%s: Not attempting", __FUNCTION__);
    559         return false;
    560     }
    561 
    562     int minBatchStart = -1;
    563     size_t minBatchPixelCount = SIZE_MAX;
    564 
    565     for(int i = 0; i <= numAppLayers - batchSize; i++) {
    566         uint32_t batchPixelCount = 0;
    567         for(int j = i; j < i + batchSize; j++) {
    568             hwc_layer_1_t* layer = &list->hwLayers[j];
    569             hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
    570             batchPixelCount += (crop.right - crop.left) *
    571                     (crop.bottom - crop.top);
    572         }
    573 
    574         if(batchPixelCount < minBatchPixelCount) {
    575             minBatchPixelCount = batchPixelCount;
    576             minBatchStart = i;
    577         }
    578     }
    579 
    580     if(minBatchStart < 0) {
    581         ALOGD_IF(isDebug(), "%s: No batch found batchSize %d numAppLayers %d",
    582                 __FUNCTION__, batchSize, numAppLayers);
    583         return false;
    584     }
    585 
    586     for(int i = 0; i < numAppLayers; i++) {
    587         if(i < minBatchStart || i >= minBatchStart + batchSize) {
    588             hwc_layer_1_t* layer = &list->hwLayers[i];
    589             if(not isSupportedForMDPComp(ctx, layer)) {
    590                 ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
    591                         __FUNCTION__, i);
    592                 return false;
    593             }
    594             mCurrentFrame.isFBComposed[i] = false;
    595         }
    596     }
    597 
    598     mCurrentFrame.fbZ = minBatchStart;
    599     mCurrentFrame.fbCount = batchSize;
    600     mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
    601 
    602     if(!arePipesAvailable(ctx, list)) {
    603         return false;
    604     }
    605 
    606     ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
    607                 __FUNCTION__, mCurrentFrame.fbZ, batchSize);
    608     return true;
    609 }
    610 
    611 bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx,
    612         hwc_display_contents_1_t* list) {
    613     if(mDpy or isSecurePresent(ctx, mDpy) or
    614             not (list->flags & HWC_GEOMETRY_CHANGED)) {
    615         return false;
    616     }
    617     return true;
    618 }
    619 
    620 bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx,
    621         hwc_display_contents_1_t* list){
    622     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    623     mCurrentFrame.reset(numAppLayers);
    624     updateYUV(ctx, list);
    625     int mdpCount = mCurrentFrame.mdpCount;
    626     int fbNeeded = int(mCurrentFrame.fbCount != 0);
    627 
    628     if(!isYuvPresent(ctx, mDpy)) {
    629         return false;
    630     }
    631 
    632     if(!mdpCount)
    633         return false;
    634 
    635     if(mdpCount > (sMaxPipesPerMixer - fbNeeded)) {
    636         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
    637         return false;
    638     }
    639 
    640     if(!arePipesAvailable(ctx, list)) {
    641         return false;
    642     }
    643 
    644     int nYuvCount = ctx->listStats[mDpy].yuvCount;
    645     for(int index = 0; index < nYuvCount ; index ++) {
    646         int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
    647         hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
    648         if(layer->planeAlpha < 0xFF) {
    649             ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
    650                     in video only mode",
    651                     __FUNCTION__);
    652             return false;
    653         }
    654         private_handle_t *hnd = (private_handle_t *)layer->handle;
    655         if(mDpy > HWC_DISPLAY_PRIMARY && isL3SecureBuffer(hnd)) {
    656             return false;
    657         }
    658     }
    659 
    660     return true;
    661 }
    662 
    663 /* Checks for conditions where YUV layers cannot be bypassed */
    664 bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
    665     if(isSkipLayer(layer)) {
    666         ALOGE("%s: Unable to bypass skipped YUV", __FUNCTION__);
    667         return false;
    668     }
    669 
    670     if(layer->transform & HWC_TRANSFORM_ROT_90 && !canUseRotator(ctx,mDpy)) {
    671         ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
    672         return false;
    673     }
    674 
    675     if(isSecuring(ctx, layer)) {
    676         ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
    677         return false;
    678     }
    679 
    680     if(!isValidDimension(ctx, layer)) {
    681         ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
    682             __FUNCTION__);
    683         return false;
    684     }
    685 
    686     return true;
    687 }
    688 
    689 bool MDPComp::batchLayers(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    690     /* Idea is to keep as many contiguous non-updating(cached) layers in FB and
    691      * send rest of them through MDP. NEVER mark an updating layer for caching.
    692      * But cached ones can be marked for MDP*/
    693 
    694     int maxBatchStart = -1;
    695     int maxBatchCount = 0;
    696 
    697     /* All or Nothing is cached. No batching needed */
    698     if(!mCurrentFrame.fbCount) {
    699         mCurrentFrame.fbZ = -1;
    700         return true;
    701     }
    702     if(!mCurrentFrame.mdpCount) {
    703         mCurrentFrame.fbZ = 0;
    704         return true;
    705     }
    706 
    707     /* Search for max number of contiguous (cached) layers */
    708     int i = 0;
    709     while (i < mCurrentFrame.layerCount) {
    710         int count = 0;
    711         while(mCurrentFrame.isFBComposed[i] && i < mCurrentFrame.layerCount) {
    712             count++; i++;
    713         }
    714         if(count > maxBatchCount) {
    715             maxBatchCount = count;
    716             maxBatchStart = i - count;
    717             mCurrentFrame.fbZ = maxBatchStart;
    718         }
    719         if(i < mCurrentFrame.layerCount) i++;
    720     }
    721 
    722     /* reset rest of the layers for MDP comp */
    723     for(int i = 0; i < mCurrentFrame.layerCount; i++) {
    724         hwc_layer_1_t* layer = &list->hwLayers[i];
    725         if(i != maxBatchStart) {
    726             //If an unsupported layer is being attempted to be pulled out we
    727             //should fail
    728             if(not isSupportedForMDPComp(ctx, layer)) {
    729                 return false;
    730             }
    731             mCurrentFrame.isFBComposed[i] = false;
    732         } else {
    733             i += maxBatchCount;
    734         }
    735     }
    736 
    737     mCurrentFrame.fbCount = maxBatchCount;
    738     mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
    739             mCurrentFrame.fbCount;
    740 
    741     ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
    742              mCurrentFrame.fbCount);
    743 
    744     return true;
    745 }
    746 
    747 void MDPComp::updateLayerCache(hwc_context_t* ctx,
    748         hwc_display_contents_1_t* list) {
    749     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    750     int fbCount = 0;
    751 
    752     for(int i = 0; i < numAppLayers; i++) {
    753         hwc_layer_1_t* layer = &list->hwLayers[i];
    754         if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
    755             fbCount++;
    756             mCurrentFrame.isFBComposed[i] = true;
    757         } else {
    758             mCurrentFrame.isFBComposed[i] = false;
    759             mCachedFrame.hnd[i] = list->hwLayers[i].handle;
    760         }
    761     }
    762 
    763     mCurrentFrame.fbCount = fbCount;
    764     mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount;
    765 
    766     ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d",__FUNCTION__,
    767             mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
    768 }
    769 
    770 void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
    771 
    772     int nYuvCount = ctx->listStats[mDpy].yuvCount;
    773     for(int index = 0;index < nYuvCount; index++){
    774         int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
    775         hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
    776 
    777         if(!isYUVDoable(ctx, layer)) {
    778             if(!mCurrentFrame.isFBComposed[nYuvIndex]) {
    779                 mCurrentFrame.isFBComposed[nYuvIndex] = true;
    780                 mCurrentFrame.fbCount++;
    781             }
    782         } else {
    783             if(mCurrentFrame.isFBComposed[nYuvIndex]) {
    784                 mCurrentFrame.isFBComposed[nYuvIndex] = false;
    785                 mCurrentFrame.fbCount--;
    786             }
    787         }
    788     }
    789 
    790     mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
    791             mCurrentFrame.fbCount;
    792     ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
    793              mCurrentFrame.fbCount);
    794 }
    795 
    796 bool MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    797     if(!allocLayerPipes(ctx, list)) {
    798         ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
    799         return false;
    800     }
    801 
    802     bool fbBatch = false;
    803     for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
    804             index++) {
    805         if(!mCurrentFrame.isFBComposed[index]) {
    806             int mdpIndex = mCurrentFrame.layerToMDP[index];
    807             hwc_layer_1_t* layer = &list->hwLayers[index];
    808 
    809             MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
    810             cur_pipe->zOrder = mdpNextZOrder++;
    811 
    812             if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
    813                 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
    814                          layer %d",__FUNCTION__, index);
    815                 return false;
    816             }
    817         } else if(fbBatch == false) {
    818                 mdpNextZOrder++;
    819                 fbBatch = true;
    820         }
    821     }
    822 
    823     return true;
    824 }
    825 
    826 bool MDPComp::programYUV(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    827     if(!allocLayerPipes(ctx, list)) {
    828         ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
    829         return false;
    830     }
    831     //If we are in this block, it means we have yuv + rgb layers both
    832     int mdpIdx = 0;
    833     for (int index = 0; index < mCurrentFrame.layerCount; index++) {
    834         if(!mCurrentFrame.isFBComposed[index]) {
    835             hwc_layer_1_t* layer = &list->hwLayers[index];
    836             int mdpIndex = mCurrentFrame.layerToMDP[index];
    837             MdpPipeInfo* cur_pipe =
    838                     mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
    839             cur_pipe->zOrder = mdpIdx++;
    840 
    841             if(configure(ctx, layer,
    842                         mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
    843                 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
    844                         layer %d",__FUNCTION__, index);
    845                 return false;
    846             }
    847         }
    848     }
    849     return true;
    850 }
    851 
    852 int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    853     const int numLayers = ctx->listStats[mDpy].numAppLayers;
    854 
    855     //reset old data
    856     mCurrentFrame.reset(numLayers);
    857 
    858     //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
    859     //do not cache the information for next draw cycle.
    860     if(numLayers > MAX_NUM_APP_LAYERS) {
    861         mCachedFrame.updateCounts(mCurrentFrame);
    862         ALOGD_IF(isDebug(), "%s: Number of App layers exceeded the limit ",
    863                 __FUNCTION__);
    864         return -1;
    865     }
    866 
    867     //Hard conditions, if not met, cannot do MDP comp
    868     if(!isFrameDoable(ctx)) {
    869         ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
    870                 __FUNCTION__);
    871         reset(numLayers, list);
    872         return -1;
    873     }
    874 
    875     //Check whether layers marked for MDP Composition is actually doable.
    876     if(isFullFrameDoable(ctx, list)) {
    877         mCurrentFrame.map();
    878         //Configure framebuffer first if applicable
    879         if(mCurrentFrame.fbZ >= 0) {
    880             if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list,
    881                         mCurrentFrame.fbZ)) {
    882                 ALOGE("%s configure framebuffer failed", __func__);
    883                 reset(numLayers, list);
    884                 return -1;
    885             }
    886         }
    887         //Acquire and Program MDP pipes
    888         if(!programMDP(ctx, list)) {
    889             reset(numLayers, list);
    890             return -1;
    891         } else { //Success
    892             //Any change in composition types needs an FB refresh
    893             mCurrentFrame.needsRedraw = false;
    894             if(mCurrentFrame.fbCount &&
    895                     ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) ||
    896                      (mCurrentFrame.fbCount != mCachedFrame.fbCount) ||
    897                      (mCurrentFrame.fbZ != mCachedFrame.fbZ) ||
    898                      (!mCurrentFrame.mdpCount) ||
    899                      (list->flags & HWC_GEOMETRY_CHANGED) ||
    900                      isSkipPresent(ctx, mDpy))) {
    901                 mCurrentFrame.needsRedraw = true;
    902             }
    903         }
    904     } else if(isOnlyVideoDoable(ctx, list)) {
    905         //All layers marked for MDP comp cannot be bypassed.
    906         //Try to compose atleast YUV layers through MDP comp and let
    907         //all the RGB layers compose in FB
    908         //Destination over
    909         mCurrentFrame.fbZ = -1;
    910         if(mCurrentFrame.fbCount)
    911             mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
    912 
    913         mCurrentFrame.map();
    914 
    915         //Configure framebuffer first if applicable
    916         if(mCurrentFrame.fbZ >= 0) {
    917             if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
    918                 ALOGE("%s configure framebuffer failed", __func__);
    919                 reset(numLayers, list);
    920                 return -1;
    921             }
    922         }
    923         if(!programYUV(ctx, list)) {
    924             reset(numLayers, list);
    925             return -1;
    926         }
    927     } else {
    928         reset(numLayers, list);
    929         return -1;
    930     }
    931 
    932     //UpdateLayerFlags
    933     setMDPCompLayerFlags(ctx, list);
    934     mCachedFrame.updateCounts(mCurrentFrame);
    935 
    936     // unlock it before calling dump function to avoid deadlock
    937     if(isDebug()) {
    938         ALOGD("GEOMETRY change: %d", (list->flags & HWC_GEOMETRY_CHANGED));
    939         android::String8 sDump("");
    940         dump(sDump);
    941         ALOGE("%s",sDump.string());
    942     }
    943 
    944     return 0;
    945 }
    946 
    947 //=============MDPCompLowRes===================================================
    948 
    949 /*
    950  * Configures pipe(s) for MDP composition
    951  */
    952 int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
    953                              PipeLayerPair& PipeLayerPair) {
    954     MdpPipeInfoLowRes& mdp_info =
    955         *(static_cast<MdpPipeInfoLowRes*>(PipeLayerPair.pipeInfo));
    956     eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
    957     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
    958     eIsFg isFg = IS_FG_OFF;
    959     eDest dest = mdp_info.index;
    960 
    961     ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
    962              __FUNCTION__, layer, zOrder, dest);
    963 
    964     return configureLowRes(ctx, layer, mDpy, mdpFlags, zOrder, isFg, dest,
    965                            &PipeLayerPair.rot);
    966 }
    967 
    968 bool MDPCompLowRes::arePipesAvailable(hwc_context_t *ctx,
    969         hwc_display_contents_1_t* list) {
    970     overlay::Overlay& ov = *ctx->mOverlay;
    971     int numPipesNeeded = mCurrentFrame.mdpCount;
    972     int availPipes = ov.availablePipes(mDpy, Overlay::MIXER_DEFAULT);
    973 
    974     //Reserve pipe for FB
    975     if(mCurrentFrame.fbCount)
    976         availPipes -= 1;
    977 
    978     if(numPipesNeeded > availPipes) {
    979         ALOGD_IF(isDebug(), "%s: Insufficient pipes, dpy %d needed %d, avail %d",
    980                 __FUNCTION__, mDpy, numPipesNeeded, availPipes);
    981         return false;
    982     }
    983 
    984     return true;
    985 }
    986 
    987 bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
    988         hwc_display_contents_1_t* list) {
    989     for(int index = 0; index < mCurrentFrame.layerCount; index++) {
    990 
    991         if(mCurrentFrame.isFBComposed[index]) continue;
    992 
    993         hwc_layer_1_t* layer = &list->hwLayers[index];
    994         private_handle_t *hnd = (private_handle_t *)layer->handle;
    995         int mdpIndex = mCurrentFrame.layerToMDP[index];
    996         PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
    997         info.pipeInfo = new MdpPipeInfoLowRes;
    998         info.rot = NULL;
    999         MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
   1000         ePipeType type = MDPCOMP_OV_ANY;
   1001 
   1002         if(isYuvBuffer(hnd)) {
   1003             type = MDPCOMP_OV_VG;
   1004         } else if(!qhwc::needsScaling(ctx, layer, mDpy)
   1005             && Overlay::getDMAMode() != Overlay::DMA_BLOCK_MODE
   1006             && ctx->mMDP.version >= qdutils::MDSS_V5) {
   1007             type = MDPCOMP_OV_DMA;
   1008         }
   1009 
   1010         pipe_info.index = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
   1011         if(pipe_info.index == ovutils::OV_INVALID) {
   1012             ALOGD_IF(isDebug(), "%s: Unable to get pipe type = %d",
   1013                 __FUNCTION__, (int) type);
   1014             return false;
   1015         }
   1016     }
   1017     return true;
   1018 }
   1019 
   1020 bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
   1021 
   1022     if(!isEnabled()) {
   1023         ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
   1024         return true;
   1025     }
   1026 
   1027     if(!ctx || !list) {
   1028         ALOGE("%s: invalid contxt or list",__FUNCTION__);
   1029         return false;
   1030     }
   1031 
   1032     if(ctx->listStats[mDpy].numAppLayers > MAX_NUM_APP_LAYERS) {
   1033         ALOGD_IF(isDebug(),"%s: Exceeding max layer count", __FUNCTION__);
   1034         return true;
   1035     }
   1036 
   1037     /* reset Invalidator */
   1038     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
   1039         idleInvalidator->markForSleep();
   1040 
   1041     overlay::Overlay& ov = *ctx->mOverlay;
   1042     LayerProp *layerProp = ctx->layerProp[mDpy];
   1043 
   1044     int numHwLayers = ctx->listStats[mDpy].numAppLayers;
   1045     for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
   1046     {
   1047         if(mCurrentFrame.isFBComposed[i]) continue;
   1048 
   1049         hwc_layer_1_t *layer = &list->hwLayers[i];
   1050         private_handle_t *hnd = (private_handle_t *)layer->handle;
   1051         if(!hnd) {
   1052             ALOGE("%s handle null", __FUNCTION__);
   1053             return false;
   1054         }
   1055 
   1056         int mdpIndex = mCurrentFrame.layerToMDP[i];
   1057 
   1058         MdpPipeInfoLowRes& pipe_info =
   1059             *(MdpPipeInfoLowRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
   1060         ovutils::eDest dest = pipe_info.index;
   1061         if(dest == ovutils::OV_INVALID) {
   1062             ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
   1063             return false;
   1064         }
   1065 
   1066         if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
   1067             continue;
   1068         }
   1069 
   1070         ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
   1071                  using  pipe: %d", __FUNCTION__, layer,
   1072                  hnd, dest );
   1073 
   1074         int fd = hnd->fd;
   1075         uint32_t offset = hnd->offset;
   1076 
   1077         if(ctx->mAD->isModeOn()) {
   1078             if(ctx->mAD->draw(ctx, fd, offset)) {
   1079                 fd = ctx->mAD->getDstFd(ctx);
   1080                 offset = ctx->mAD->getDstOffset(ctx);
   1081             }
   1082         }
   1083 
   1084         Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
   1085         if(rot) {
   1086             if(!rot->queueBuffer(fd, offset))
   1087                 return false;
   1088             fd = rot->getDstMemId();
   1089             offset = rot->getDstOffset();
   1090         }
   1091 
   1092         if (!ov.queueBuffer(fd, offset, dest)) {
   1093             ALOGE("%s: queueBuffer failed for display:%d ", __FUNCTION__, mDpy);
   1094             return false;
   1095         }
   1096 
   1097         layerProp[i].mFlags &= ~HWC_MDPCOMP;
   1098     }
   1099     return true;
   1100 }
   1101 
   1102 //=============MDPCompHighRes===================================================
   1103 
   1104 int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
   1105         hwc_display_contents_1_t* list,
   1106         int mixer) {
   1107     int pipesNeeded = 0;
   1108     const int xres = ctx->dpyAttr[mDpy].xres;
   1109 
   1110     const int lSplit = getLeftSplit(ctx, mDpy);
   1111 
   1112     for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
   1113         if(!mCurrentFrame.isFBComposed[i]) {
   1114             hwc_layer_1_t* layer = &list->hwLayers[i];
   1115             hwc_rect_t dst = layer->displayFrame;
   1116             if(mixer == Overlay::MIXER_LEFT && dst.left < lSplit) {
   1117                 pipesNeeded++;
   1118             } else if(mixer == Overlay::MIXER_RIGHT && dst.right > lSplit) {
   1119                 pipesNeeded++;
   1120             }
   1121         }
   1122     }
   1123     return pipesNeeded;
   1124 }
   1125 
   1126 bool MDPCompHighRes::arePipesAvailable(hwc_context_t *ctx,
   1127         hwc_display_contents_1_t* list) {
   1128     overlay::Overlay& ov = *ctx->mOverlay;
   1129 
   1130     for(int i = 0; i < Overlay::MIXER_MAX; i++) {
   1131         int numPipesNeeded = pipesNeeded(ctx, list, i);
   1132         int availPipes = ov.availablePipes(mDpy, i);
   1133 
   1134         //Reserve pipe(s)for FB
   1135         if(mCurrentFrame.fbCount)
   1136             availPipes -= 1;
   1137 
   1138         if(numPipesNeeded > availPipes) {
   1139             ALOGD_IF(isDebug(), "%s: Insufficient pipes for "
   1140                      "dpy %d mixer %d needed %d, avail %d",
   1141                      __FUNCTION__, mDpy, i, numPipesNeeded, availPipes);
   1142             return false;
   1143         }
   1144     }
   1145     return true;
   1146 }
   1147 
   1148 bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
   1149         MdpPipeInfoHighRes& pipe_info,
   1150         ePipeType type) {
   1151     const int xres = ctx->dpyAttr[mDpy].xres;
   1152     const int lSplit = getLeftSplit(ctx, mDpy);
   1153 
   1154     hwc_rect_t dst = layer->displayFrame;
   1155     pipe_info.lIndex = ovutils::OV_INVALID;
   1156     pipe_info.rIndex = ovutils::OV_INVALID;
   1157 
   1158     if (dst.left < lSplit) {
   1159         pipe_info.lIndex = getMdpPipe(ctx, type, Overlay::MIXER_LEFT);
   1160         if(pipe_info.lIndex == ovutils::OV_INVALID)
   1161             return false;
   1162     }
   1163 
   1164     if(dst.right > lSplit) {
   1165         pipe_info.rIndex = getMdpPipe(ctx, type, Overlay::MIXER_RIGHT);
   1166         if(pipe_info.rIndex == ovutils::OV_INVALID)
   1167             return false;
   1168     }
   1169 
   1170     return true;
   1171 }
   1172 
   1173 bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx,
   1174         hwc_display_contents_1_t* list) {
   1175     for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
   1176 
   1177         if(mCurrentFrame.isFBComposed[index]) continue;
   1178 
   1179         hwc_layer_1_t* layer = &list->hwLayers[index];
   1180         private_handle_t *hnd = (private_handle_t *)layer->handle;
   1181         int mdpIndex = mCurrentFrame.layerToMDP[index];
   1182         PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
   1183         info.pipeInfo = new MdpPipeInfoHighRes;
   1184         info.rot = NULL;
   1185         MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
   1186         ePipeType type = MDPCOMP_OV_ANY;
   1187 
   1188         if(isYuvBuffer(hnd)) {
   1189             type = MDPCOMP_OV_VG;
   1190         } else if(!qhwc::needsScaling(ctx, layer, mDpy)
   1191             && Overlay::getDMAMode() != Overlay::DMA_BLOCK_MODE
   1192             && ctx->mMDP.version >= qdutils::MDSS_V5) {
   1193             type = MDPCOMP_OV_DMA;
   1194         }
   1195 
   1196         if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
   1197             ALOGD_IF(isDebug(), "%s: Unable to get pipe for type = %d",
   1198                     __FUNCTION__, (int) type);
   1199             return false;
   1200         }
   1201     }
   1202     return true;
   1203 }
   1204 
   1205 /*
   1206  * Configures pipe(s) for MDP composition
   1207  */
   1208 int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
   1209         PipeLayerPair& PipeLayerPair) {
   1210     MdpPipeInfoHighRes& mdp_info =
   1211         *(static_cast<MdpPipeInfoHighRes*>(PipeLayerPair.pipeInfo));
   1212     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
   1213     eIsFg isFg = IS_FG_OFF;
   1214     eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
   1215     eDest lDest = mdp_info.lIndex;
   1216     eDest rDest = mdp_info.rIndex;
   1217 
   1218     ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
   1219              "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
   1220 
   1221     return configureHighRes(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg, lDest,
   1222                             rDest, &PipeLayerPair.rot);
   1223 }
   1224 
   1225 bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
   1226 
   1227     if(!isEnabled()) {
   1228         ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
   1229         return true;
   1230     }
   1231 
   1232     if(!ctx || !list) {
   1233         ALOGE("%s: invalid contxt or list",__FUNCTION__);
   1234         return false;
   1235     }
   1236 
   1237     if(ctx->listStats[mDpy].numAppLayers > MAX_NUM_APP_LAYERS) {
   1238         ALOGD_IF(isDebug(),"%s: Exceeding max layer count", __FUNCTION__);
   1239         return true;
   1240     }
   1241 
   1242     /* reset Invalidator */
   1243     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
   1244         idleInvalidator->markForSleep();
   1245 
   1246     overlay::Overlay& ov = *ctx->mOverlay;
   1247     LayerProp *layerProp = ctx->layerProp[mDpy];
   1248 
   1249     int numHwLayers = ctx->listStats[mDpy].numAppLayers;
   1250     for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
   1251     {
   1252         if(mCurrentFrame.isFBComposed[i]) continue;
   1253 
   1254         hwc_layer_1_t *layer = &list->hwLayers[i];
   1255         private_handle_t *hnd = (private_handle_t *)layer->handle;
   1256         if(!hnd) {
   1257             ALOGE("%s handle null", __FUNCTION__);
   1258             return false;
   1259         }
   1260 
   1261         if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
   1262             continue;
   1263         }
   1264 
   1265         int mdpIndex = mCurrentFrame.layerToMDP[i];
   1266 
   1267         MdpPipeInfoHighRes& pipe_info =
   1268             *(MdpPipeInfoHighRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
   1269         Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
   1270 
   1271         ovutils::eDest indexL = pipe_info.lIndex;
   1272         ovutils::eDest indexR = pipe_info.rIndex;
   1273 
   1274         int fd = hnd->fd;
   1275         int offset = hnd->offset;
   1276 
   1277         if(ctx->mAD->isModeOn()) {
   1278             if(ctx->mAD->draw(ctx, fd, offset)) {
   1279                 fd = ctx->mAD->getDstFd(ctx);
   1280                 offset = ctx->mAD->getDstOffset(ctx);
   1281             }
   1282         }
   1283 
   1284         if(rot) {
   1285             rot->queueBuffer(fd, offset);
   1286             fd = rot->getDstMemId();
   1287             offset = rot->getDstOffset();
   1288         }
   1289 
   1290         //************* play left mixer **********
   1291         if(indexL != ovutils::OV_INVALID) {
   1292             ovutils::eDest destL = (ovutils::eDest)indexL;
   1293             ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
   1294                      using  pipe: %d", __FUNCTION__, layer, hnd, indexL );
   1295             if (!ov.queueBuffer(fd, offset, destL)) {
   1296                 ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__);
   1297                 return false;
   1298             }
   1299         }
   1300 
   1301         //************* play right mixer **********
   1302         if(indexR != ovutils::OV_INVALID) {
   1303             ovutils::eDest destR = (ovutils::eDest)indexR;
   1304             ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
   1305                      using  pipe: %d", __FUNCTION__, layer, hnd, indexR );
   1306             if (!ov.queueBuffer(fd, offset, destR)) {
   1307                 ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__);
   1308                 return false;
   1309             }
   1310         }
   1311 
   1312         layerProp[i].mFlags &= ~HWC_MDPCOMP;
   1313     }
   1314 
   1315     return true;
   1316 }
   1317 }; //namespace
   1318 
   1319