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