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 "external.h"
     23 #include "qdMetaData.h"
     24 #include "mdp_version.h"
     25 #include <overlayRotator.h>
     26 
     27 using overlay::Rotator;
     28 using namespace overlay::utils;
     29 namespace ovutils = overlay::utils;
     30 
     31 namespace qhwc {
     32 
     33 //==============MDPComp========================================================
     34 
     35 IdleInvalidator *MDPComp::idleInvalidator = NULL;
     36 bool MDPComp::sIdleFallBack = false;
     37 bool MDPComp::sDebugLogs = false;
     38 bool MDPComp::sEnabled = false;
     39 int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
     40 
     41 MDPComp* MDPComp::getObject(const int& width, int dpy) {
     42     if(width <= MAX_DISPLAY_DIM) {
     43         return new MDPCompLowRes(dpy);
     44     } else {
     45         return new MDPCompHighRes(dpy);
     46     }
     47 }
     48 
     49 MDPComp::MDPComp(int dpy):mDpy(dpy){};
     50 
     51 void MDPComp::dump(android::String8& buf)
     52 {
     53     dumpsys_log(buf,"HWC Map for Dpy: %s \n",
     54                 mDpy ? "\"EXTERNAL\"" : "\"PRIMARY\"");
     55     dumpsys_log(buf,"PREV_FRAME: layerCount:%2d    mdpCount:%2d \
     56                 cacheCount:%2d \n", mCachedFrame.layerCount,
     57                 mCachedFrame.mdpCount, mCachedFrame.cacheCount);
     58     dumpsys_log(buf,"CURR_FRAME: layerCount:%2d    mdpCount:%2d \
     59                 fbCount:%2d \n", mCurrentFrame.layerCount,
     60                 mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
     61     dumpsys_log(buf,"needsFBRedraw:%3s  pipesUsed:%2d  MaxPipesPerMixer: %d \n",
     62                 (mCurrentFrame.needsRedraw? "YES" : "NO"),
     63                 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
     64     dumpsys_log(buf," ---------------------------------------------  \n");
     65     dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype  |  Z  \n");
     66     dumpsys_log(buf," ---------------------------------------------  \n");
     67     for(int index = 0; index < mCurrentFrame.layerCount; index++ )
     68         dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
     69                     index,
     70                     (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
     71                     mCurrentFrame.layerToMDP[index],
     72                     (mCurrentFrame.isFBComposed[index] ?
     73                      (mCurrentFrame.needsRedraw ? "GLES" : "CACHE") : "MDP"),
     74                     (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
     75     mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
     76     dumpsys_log(buf,"\n");
     77 }
     78 
     79 bool MDPComp::init(hwc_context_t *ctx) {
     80 
     81     if(!ctx) {
     82         ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
     83         return false;
     84     }
     85 
     86     char property[PROPERTY_VALUE_MAX];
     87 
     88     sEnabled = false;
     89     if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
     90        (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
     91         (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
     92         sEnabled = true;
     93     }
     94 
     95     sDebugLogs = false;
     96     if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
     97         if(atoi(property) != 0)
     98             sDebugLogs = true;
     99     }
    100 
    101     sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
    102     if(property_get("debug.mdpcomp.maxpermixer", property, NULL) > 0) {
    103         if(atoi(property) != 0)
    104             sMaxPipesPerMixer = true;
    105     }
    106 
    107     if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
    108         // Idle invalidation is not necessary on command mode panels
    109         long idle_timeout = DEFAULT_IDLE_TIME;
    110         if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
    111             if(atoi(property) != 0)
    112                 idle_timeout = atoi(property);
    113         }
    114 
    115         //create Idle Invalidator only when not disabled through property
    116         if(idle_timeout != -1)
    117             idleInvalidator = IdleInvalidator::getInstance();
    118 
    119         if(idleInvalidator == NULL) {
    120             ALOGE("%s: failed to instantiate idleInvalidator object",
    121                   __FUNCTION__);
    122         } else {
    123             idleInvalidator->init(timeout_handler, ctx, idle_timeout);
    124         }
    125     }
    126     return true;
    127 }
    128 
    129 void MDPComp::timeout_handler(void *udata) {
    130     struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
    131 
    132     if(!ctx) {
    133         ALOGE("%s: received empty data in timer callback", __FUNCTION__);
    134         return;
    135     }
    136 
    137     if(!ctx->proc) {
    138         ALOGE("%s: HWC proc not registered", __FUNCTION__);
    139         return;
    140     }
    141     sIdleFallBack = true;
    142     /* Trigger SF to redraw the current frame */
    143     ctx->proc->invalidate(ctx->proc);
    144 }
    145 
    146 void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
    147                                    hwc_display_contents_1_t* list) {
    148     LayerProp *layerProp = ctx->layerProp[mDpy];
    149 
    150     for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
    151         hwc_layer_1_t* layer = &(list->hwLayers[index]);
    152         if(!mCurrentFrame.isFBComposed[index]) {
    153             layerProp[index].mFlags |= HWC_MDPCOMP;
    154             layer->compositionType = HWC_OVERLAY;
    155             layer->hints |= HWC_HINT_CLEAR_FB;
    156             mCachedFrame.hnd[index] = NULL;
    157         } else {
    158             if(!mCurrentFrame.needsRedraw)
    159                 layer->compositionType = HWC_OVERLAY;
    160         }
    161     }
    162 }
    163 
    164 /*
    165  * Sets up BORDERFILL as default base pipe and detaches RGB0.
    166  * Framebuffer is always updated using PLAY ioctl.
    167  */
    168 bool MDPComp::setupBasePipe(hwc_context_t *ctx) {
    169     const int dpy = HWC_DISPLAY_PRIMARY;
    170     int fb_stride = ctx->dpyAttr[dpy].stride;
    171     int fb_width = ctx->dpyAttr[dpy].xres;
    172     int fb_height = ctx->dpyAttr[dpy].yres;
    173     int fb_fd = ctx->dpyAttr[dpy].fd;
    174 
    175     mdp_overlay ovInfo;
    176     msmfb_overlay_data ovData;
    177     memset(&ovInfo, 0, sizeof(mdp_overlay));
    178     memset(&ovData, 0, sizeof(msmfb_overlay_data));
    179 
    180     ovInfo.src.format = MDP_RGB_BORDERFILL;
    181     ovInfo.src.width  = fb_width;
    182     ovInfo.src.height = fb_height;
    183     ovInfo.src_rect.w = fb_width;
    184     ovInfo.src_rect.h = fb_height;
    185     ovInfo.dst_rect.w = fb_width;
    186     ovInfo.dst_rect.h = fb_height;
    187     ovInfo.id = MSMFB_NEW_REQUEST;
    188 
    189     if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
    190         ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
    191               strerror(errno));
    192         return false;
    193     }
    194 
    195     ovData.id = ovInfo.id;
    196     if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
    197         ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
    198               strerror(errno));
    199         return false;
    200     }
    201     return true;
    202 }
    203 
    204 MDPComp::FrameInfo::FrameInfo() {
    205     memset(&mdpToLayer, 0, sizeof(mdpToLayer));
    206     reset(0);
    207 }
    208 
    209 void MDPComp::FrameInfo::reset(const int& numLayers) {
    210     for(int i = 0 ; i < MAX_PIPES_PER_MIXER; i++ ) {
    211         if(mdpToLayer[i].pipeInfo) {
    212             delete mdpToLayer[i].pipeInfo;
    213             mdpToLayer[i].pipeInfo = NULL;
    214             //We dont own the rotator
    215             mdpToLayer[i].rot = NULL;
    216         }
    217     }
    218 
    219     memset(&mdpToLayer, 0, sizeof(mdpToLayer));
    220     memset(&layerToMDP, -1, sizeof(layerToMDP));
    221     memset(&isFBComposed, 1, sizeof(isFBComposed));
    222 
    223     layerCount = numLayers;
    224     fbCount = numLayers;
    225     mdpCount = 0;
    226     needsRedraw = true;
    227     fbZ = 0;
    228 }
    229 
    230 void MDPComp::FrameInfo::map() {
    231     // populate layer and MDP maps
    232     int mdpIdx = 0;
    233     for(int idx = 0; idx < layerCount; idx++) {
    234         if(!isFBComposed[idx]) {
    235             mdpToLayer[mdpIdx].listIndex = idx;
    236             layerToMDP[idx] = mdpIdx++;
    237         }
    238     }
    239 }
    240 
    241 MDPComp::LayerCache::LayerCache() {
    242     reset();
    243 }
    244 
    245 void MDPComp::LayerCache::reset() {
    246     memset(&hnd, 0, sizeof(hnd));
    247     mdpCount = 0;
    248     cacheCount = 0;
    249     layerCount = 0;
    250     fbZ = -1;
    251 }
    252 
    253 void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
    254     const int numAppLayers = list->numHwLayers - 1;
    255     for(int i = 0; i < numAppLayers; i++) {
    256         hnd[i] = list->hwLayers[i].handle;
    257     }
    258 }
    259 
    260 void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
    261     mdpCount = curFrame.mdpCount;
    262     cacheCount = curFrame.fbCount;
    263     layerCount = curFrame.layerCount;
    264     fbZ = curFrame.fbZ;
    265 }
    266 
    267 bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
    268     const int dpy = HWC_DISPLAY_PRIMARY;
    269     private_handle_t *hnd = (private_handle_t *)layer->handle;
    270 
    271     if(!hnd) {
    272         ALOGE("%s: layer handle is NULL", __FUNCTION__);
    273         return false;
    274     }
    275 
    276     int hw_w = ctx->dpyAttr[mDpy].xres;
    277     int hw_h = ctx->dpyAttr[mDpy].yres;
    278 
    279     hwc_rect_t crop = layer->sourceCrop;
    280     hwc_rect_t dst = layer->displayFrame;
    281 
    282     if(dst.left < 0 || dst.top < 0 || dst.right > hw_w || dst.bottom > hw_h) {
    283        hwc_rect_t scissor = {0, 0, hw_w, hw_h };
    284        qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
    285     }
    286 
    287     int crop_w = crop.right - crop.left;
    288     int crop_h = crop.bottom - crop.top;
    289     int dst_w = dst.right - dst.left;
    290     int dst_h = dst.bottom - dst.top;
    291     float w_dscale = ceilf((float)crop_w / (float)dst_w);
    292     float h_dscale = ceilf((float)crop_h / (float)dst_h);
    293 
    294     //Workaround for MDP HW limitation in DSI command mode panels where
    295     //FPS will not go beyond 30 if buffers on RGB pipes are of width < 5
    296 
    297     if((crop_w < 5)||(crop_h < 5))
    298         return false;
    299 
    300     if(ctx->mMDP.version >= qdutils::MDSS_V5) {
    301         /* Workaround for downscales larger than 4x.
    302          * Will be removed once decimator block is enabled for MDSS
    303          */
    304         if(w_dscale > 4.0f || h_dscale > 4.0f)
    305             return false;
    306     } else {
    307         if(w_dscale > 8.0f || h_dscale > 8.0f)
    308             // MDP 4 supports 1/8 downscale
    309             return false;
    310     }
    311 
    312     return true;
    313 }
    314 
    315 ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type) {
    316     overlay::Overlay& ov = *ctx->mOverlay;
    317     ovutils::eDest mdp_pipe = ovutils::OV_INVALID;
    318 
    319     switch(type) {
    320     case MDPCOMP_OV_DMA:
    321         mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, mDpy);
    322         if(mdp_pipe != ovutils::OV_INVALID) {
    323             ctx->mDMAInUse = true;
    324             return mdp_pipe;
    325         }
    326     case MDPCOMP_OV_ANY:
    327     case MDPCOMP_OV_RGB:
    328         mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
    329         if(mdp_pipe != ovutils::OV_INVALID) {
    330             return mdp_pipe;
    331         }
    332 
    333         if(type == MDPCOMP_OV_RGB) {
    334             //Requested only for RGB pipe
    335             break;
    336         }
    337     case  MDPCOMP_OV_VG:
    338         return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy);
    339     default:
    340         ALOGE("%s: Invalid pipe type",__FUNCTION__);
    341         return ovutils::OV_INVALID;
    342     };
    343     return ovutils::OV_INVALID;
    344 }
    345 
    346 bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
    347     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    348     bool ret = true;
    349 
    350     if(!isEnabled()) {
    351         ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
    352         ret = false;
    353     } else if(ctx->mExtDispConfiguring) {
    354         ALOGD_IF( isDebug(),"%s: External Display connection is pending",
    355                   __FUNCTION__);
    356         ret = false;
    357     } else if(ctx->mVideoTransFlag) {
    358         ALOGD_IF(isDebug(), "%s: MDP Comp. video transition padding round",
    359                 __FUNCTION__);
    360         ret = false;
    361     }
    362     return ret;
    363 }
    364 
    365 /* Checks for conditions where all the layers marked for MDP comp cannot be
    366  * bypassed. On such conditions we try to bypass atleast YUV layers */
    367 bool MDPComp::isFullFrameDoable(hwc_context_t *ctx,
    368                                 hwc_display_contents_1_t* list){
    369 
    370     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    371 
    372     if(sIdleFallBack) {
    373         ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
    374         return false;
    375     }
    376 
    377     if(mDpy > HWC_DISPLAY_PRIMARY){
    378         ALOGD_IF(isDebug(), "%s: Cannot support External display(s)",
    379                  __FUNCTION__);
    380         return false;
    381     }
    382 
    383     if(isSkipPresent(ctx, mDpy)) {
    384         ALOGD_IF(isDebug(),"%s: SKIP present: %d",
    385                 __FUNCTION__,
    386                 isSkipPresent(ctx, mDpy));
    387         return false;
    388     }
    389 
    390     if(ctx->listStats[mDpy].planeAlpha
    391                      && ctx->mMDP.version >= qdutils::MDSS_V5) {
    392         ALOGD_IF(isDebug(), "%s: plane alpha not implemented on MDSS",
    393                  __FUNCTION__);
    394         return false;
    395     }
    396 
    397     if(ctx->listStats[mDpy].needsAlphaScale
    398        && ctx->mMDP.version < qdutils::MDSS_V5) {
    399         ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
    400         return false;
    401     }
    402 
    403     //MDP composition is not efficient if layer needs rotator.
    404     for(int i = 0; i < numAppLayers; ++i) {
    405         // As MDP h/w supports flip operation, use MDP comp only for
    406         // 180 transforms. Fail for any transform involving 90 (90, 270).
    407         hwc_layer_1_t* layer = &list->hwLayers[i];
    408         private_handle_t *hnd = (private_handle_t *)layer->handle;
    409         if(isYuvBuffer(hnd) ) {
    410             if(isSecuring(ctx, layer)) {
    411                 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
    412                 return false;
    413             }
    414         } else if(layer->transform & HWC_TRANSFORM_ROT_90) {
    415             ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
    416             return false;
    417         }
    418 
    419         if(!isValidDimension(ctx,layer)) {
    420             ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
    421                 __FUNCTION__);
    422             return false;
    423         }
    424     }
    425 
    426     //If all above hard conditions are met we can do full or partial MDP comp.
    427     bool ret = false;
    428     if(fullMDPComp(ctx, list)) {
    429         ret = true;
    430     } else if (partialMDPComp(ctx, list)) {
    431         ret = true;
    432     }
    433     return ret;
    434 }
    435 
    436 bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    437     //Setup mCurrentFrame
    438     mCurrentFrame.mdpCount = mCurrentFrame.layerCount;
    439     mCurrentFrame.fbCount = 0;
    440     mCurrentFrame.fbZ = -1;
    441     memset(&mCurrentFrame.isFBComposed, 0, sizeof(mCurrentFrame.isFBComposed));
    442 
    443     int mdpCount = mCurrentFrame.mdpCount;
    444     if(mdpCount > sMaxPipesPerMixer) {
    445         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
    446         return false;
    447     }
    448 
    449     int numPipesNeeded = pipesNeeded(ctx, list);
    450     int availPipes = getAvailablePipes(ctx);
    451 
    452     if(numPipesNeeded > availPipes) {
    453         ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
    454                 __FUNCTION__, numPipesNeeded, availPipes);
    455         return false;
    456     }
    457 
    458     return true;
    459 }
    460 
    461 bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
    462 {
    463     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    464     //Setup mCurrentFrame
    465     mCurrentFrame.reset(numAppLayers);
    466     updateLayerCache(ctx, list);
    467     updateYUV(ctx, list);
    468     batchLayers(); //sets up fbZ also
    469 
    470     int mdpCount = mCurrentFrame.mdpCount;
    471     if(mdpCount > (sMaxPipesPerMixer - 1)) { // -1 since FB is used
    472         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
    473         return false;
    474     }
    475 
    476     int numPipesNeeded = pipesNeeded(ctx, list);
    477     int availPipes = getAvailablePipes(ctx);
    478 
    479     if(numPipesNeeded > availPipes) {
    480         ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
    481                 __FUNCTION__, numPipesNeeded, availPipes);
    482         return false;
    483     }
    484 
    485     return true;
    486 }
    487 
    488 bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx,
    489         hwc_display_contents_1_t* list){
    490     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    491     mCurrentFrame.reset(numAppLayers);
    492     updateYUV(ctx, list);
    493     int mdpCount = mCurrentFrame.mdpCount;
    494     int fbNeeded = int(mCurrentFrame.fbCount != 0);
    495 
    496     if(!isYuvPresent(ctx, mDpy)) {
    497         return false;
    498     }
    499 
    500     if(!mdpCount)
    501         return false;
    502 
    503     if(mdpCount > (sMaxPipesPerMixer - fbNeeded)) {
    504         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
    505         return false;
    506     }
    507 
    508     int numPipesNeeded = pipesNeeded(ctx, list);
    509     int availPipes = getAvailablePipes(ctx);
    510     if(numPipesNeeded > availPipes) {
    511         ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d",
    512                 __FUNCTION__, numPipesNeeded, availPipes);
    513         return false;
    514     }
    515 
    516     int nYuvCount = ctx->listStats[mDpy].yuvCount;
    517     for(int index = 0; index < nYuvCount ; index ++) {
    518         int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
    519         hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
    520         if(layer->planeAlpha < 0xFF) {
    521             ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
    522                     when sandwiched",
    523                     __FUNCTION__);
    524             return false;
    525         }
    526     }
    527 
    528     return true;
    529 }
    530 
    531 /* Checks for conditions where YUV layers cannot be bypassed */
    532 bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
    533 
    534     if(isSkipLayer(layer)) {
    535         ALOGE("%s: Unable to bypass skipped YUV", __FUNCTION__);
    536         return false;
    537     }
    538 
    539     if(ctx->mNeedsRotator && ctx->mDMAInUse) {
    540         ALOGE("%s: No DMA for Rotator",__FUNCTION__);
    541         return false;
    542     }
    543 
    544     if(isSecuring(ctx, layer)) {
    545         ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
    546         return false;
    547     }
    548 
    549     if(!isValidDimension(ctx, layer)) {
    550         ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
    551             __FUNCTION__);
    552         return false;
    553     }
    554 
    555     return true;
    556 }
    557 
    558 void  MDPComp::batchLayers() {
    559     /* Idea is to keep as many contiguous non-updating(cached) layers in FB and
    560      * send rest of them through MDP. NEVER mark an updating layer for caching.
    561      * But cached ones can be marked for MDP*/
    562 
    563     int maxBatchStart = -1;
    564     int maxBatchCount = 0;
    565 
    566     /* All or Nothing is cached. No batching needed */
    567     if(!mCurrentFrame.fbCount) {
    568         mCurrentFrame.fbZ = -1;
    569         return;
    570     }
    571     if(!mCurrentFrame.mdpCount) {
    572         mCurrentFrame.fbZ = 0;
    573         return;
    574     }
    575 
    576     /* Search for max number of contiguous (cached) layers */
    577     int i = 0;
    578     while (i < mCurrentFrame.layerCount) {
    579         int count = 0;
    580         while(mCurrentFrame.isFBComposed[i] && i < mCurrentFrame.layerCount) {
    581             count++; i++;
    582         }
    583         if(count > maxBatchCount) {
    584             maxBatchCount = count;
    585             maxBatchStart = i - count;
    586             mCurrentFrame.fbZ = maxBatchStart;
    587         }
    588         if(i < mCurrentFrame.layerCount) i++;
    589     }
    590 
    591     /* reset rest of the layers for MDP comp */
    592     for(int i = 0; i < mCurrentFrame.layerCount; i++) {
    593         if(i != maxBatchStart){
    594             mCurrentFrame.isFBComposed[i] = false;
    595         } else {
    596             i += maxBatchCount;
    597         }
    598     }
    599 
    600     mCurrentFrame.fbCount = maxBatchCount;
    601     mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
    602             mCurrentFrame.fbCount;
    603 
    604     ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
    605              mCurrentFrame.fbCount);
    606 }
    607 
    608 void MDPComp::updateLayerCache(hwc_context_t* ctx,
    609                                hwc_display_contents_1_t* list) {
    610 
    611     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
    612     int numCacheableLayers = 0;
    613 
    614     for(int i = 0; i < numAppLayers; i++) {
    615         if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
    616             numCacheableLayers++;
    617             mCurrentFrame.isFBComposed[i] = true;
    618         } else {
    619             mCurrentFrame.isFBComposed[i] = false;
    620             mCachedFrame.hnd[i] = list->hwLayers[i].handle;
    621         }
    622     }
    623 
    624     mCurrentFrame.fbCount = numCacheableLayers;
    625     mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
    626             mCurrentFrame.fbCount;
    627     ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__, numCacheableLayers);
    628 }
    629 
    630 int MDPComp::getAvailablePipes(hwc_context_t* ctx) {
    631     int numDMAPipes = qdutils::MDPVersion::getInstance().getDMAPipes();
    632     overlay::Overlay& ov = *ctx->mOverlay;
    633 
    634     int numAvailable = ov.availablePipes(mDpy);
    635 
    636     //Reserve DMA for rotator
    637     if(ctx->mNeedsRotator)
    638         numAvailable -= numDMAPipes;
    639 
    640     //Reserve pipe(s)for FB
    641     if(mCurrentFrame.fbCount)
    642         numAvailable -= pipesForFB();
    643 
    644     return numAvailable;
    645 }
    646 
    647 void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
    648 
    649     int nYuvCount = ctx->listStats[mDpy].yuvCount;
    650     for(int index = 0;index < nYuvCount; index++){
    651         int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
    652         hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
    653 
    654         if(!isYUVDoable(ctx, layer)) {
    655             if(!mCurrentFrame.isFBComposed[nYuvIndex]) {
    656                 mCurrentFrame.isFBComposed[nYuvIndex] = true;
    657                 mCurrentFrame.fbCount++;
    658             }
    659         } else {
    660             if(mCurrentFrame.isFBComposed[nYuvIndex]) {
    661                 mCurrentFrame.isFBComposed[nYuvIndex] = false;
    662                 mCurrentFrame.fbCount--;
    663             }
    664         }
    665     }
    666 
    667     mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
    668             mCurrentFrame.fbCount;
    669     ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
    670              mCurrentFrame.fbCount);
    671 }
    672 
    673 bool MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    674     ctx->mDMAInUse = false;
    675     if(!allocLayerPipes(ctx, list)) {
    676         ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
    677         return false;
    678     }
    679 
    680     bool fbBatch = false;
    681     for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
    682             index++) {
    683         if(!mCurrentFrame.isFBComposed[index]) {
    684             int mdpIndex = mCurrentFrame.layerToMDP[index];
    685             hwc_layer_1_t* layer = &list->hwLayers[index];
    686 
    687             MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
    688             cur_pipe->zOrder = mdpNextZOrder++;
    689 
    690             if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
    691                 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
    692                          layer %d",__FUNCTION__, index);
    693                 return false;
    694             }
    695         } else if(fbBatch == false) {
    696                 mdpNextZOrder++;
    697                 fbBatch = true;
    698         }
    699     }
    700 
    701     return true;
    702 }
    703 
    704 bool MDPComp::programYUV(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    705     if(!allocLayerPipes(ctx, list)) {
    706         ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
    707         return false;
    708     }
    709     //If we are in this block, it means we have yuv + rgb layers both
    710     int mdpIdx = 0;
    711     for (int index = 0; index < mCurrentFrame.layerCount; index++) {
    712         if(!mCurrentFrame.isFBComposed[index]) {
    713             hwc_layer_1_t* layer = &list->hwLayers[index];
    714             int mdpIndex = mCurrentFrame.layerToMDP[index];
    715             MdpPipeInfo* cur_pipe =
    716                     mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
    717             cur_pipe->zOrder = mdpIdx++;
    718 
    719             if(configure(ctx, layer,
    720                         mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
    721                 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
    722                         layer %d",__FUNCTION__, index);
    723                 return false;
    724             }
    725         }
    726     }
    727     return true;
    728 }
    729 
    730 int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    731 
    732     //reset old data
    733     const int numLayers = ctx->listStats[mDpy].numAppLayers;
    734     mCurrentFrame.reset(numLayers);
    735 
    736     //Hard conditions, if not met, cannot do MDP comp
    737     if(!isFrameDoable(ctx)) {
    738         ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
    739                   __FUNCTION__);
    740         mCurrentFrame.reset(numLayers);
    741         mCachedFrame.cacheAll(list);
    742         mCachedFrame.updateCounts(mCurrentFrame);
    743         return 0;
    744     }
    745 
    746     //Check whether layers marked for MDP Composition is actually doable.
    747     if(isFullFrameDoable(ctx, list)){
    748         mCurrentFrame.map();
    749         //Acquire and Program MDP pipes
    750         if(!programMDP(ctx, list)) {
    751             mCurrentFrame.reset(numLayers);
    752             mCachedFrame.cacheAll(list);
    753         } else { //Success
    754             //Any change in composition types needs an FB refresh
    755             mCurrentFrame.needsRedraw = false;
    756             if(mCurrentFrame.fbCount &&
    757                     ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) ||
    758                      (mCurrentFrame.fbCount != mCachedFrame.cacheCount) ||
    759                      (mCurrentFrame.fbZ != mCachedFrame.fbZ) ||
    760                      (!mCurrentFrame.mdpCount) ||
    761                      (list->flags & HWC_GEOMETRY_CHANGED) ||
    762                      isSkipPresent(ctx, mDpy) ||
    763                      (mDpy > HWC_DISPLAY_PRIMARY))) {
    764                 mCurrentFrame.needsRedraw = true;
    765             }
    766         }
    767     } else if(isOnlyVideoDoable(ctx, list)) {
    768         //All layers marked for MDP comp cannot be bypassed.
    769         //Try to compose atleast YUV layers through MDP comp and let
    770         //all the RGB layers compose in FB
    771         //Destination over
    772         mCurrentFrame.fbZ = -1;
    773         if(mCurrentFrame.fbCount)
    774             mCurrentFrame.fbZ = ctx->listStats[mDpy].yuvCount;
    775 
    776         mCurrentFrame.map();
    777         if(!programYUV(ctx, list)) {
    778             mCurrentFrame.reset(numLayers);
    779             mCachedFrame.cacheAll(list);
    780         }
    781     } else {
    782         mCurrentFrame.reset(numLayers);
    783         mCachedFrame.cacheAll(list);
    784     }
    785 
    786     //UpdateLayerFlags
    787     setMDPCompLayerFlags(ctx, list);
    788     mCachedFrame.updateCounts(mCurrentFrame);
    789 
    790     if(isDebug()) {
    791         ALOGD("GEOMETRY change: %d", (list->flags & HWC_GEOMETRY_CHANGED));
    792         android::String8 sDump("");
    793         dump(sDump);
    794         ALOGE("%s",sDump.string());
    795     }
    796 
    797     return mCurrentFrame.fbZ;
    798 }
    799 
    800 //=============MDPCompLowRes===================================================
    801 
    802 /*
    803  * Configures pipe(s) for MDP composition
    804  */
    805 int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
    806                              PipeLayerPair& PipeLayerPair) {
    807     MdpPipeInfoLowRes& mdp_info =
    808         *(static_cast<MdpPipeInfoLowRes*>(PipeLayerPair.pipeInfo));
    809     eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
    810     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
    811     eIsFg isFg = IS_FG_OFF;
    812     eDest dest = mdp_info.index;
    813 
    814     ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
    815              __FUNCTION__, layer, zOrder, dest);
    816 
    817     return configureLowRes(ctx, layer, mDpy, mdpFlags, zOrder, isFg, dest,
    818                            &PipeLayerPair.rot);
    819 }
    820 
    821 int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx,
    822                                hwc_display_contents_1_t* list) {
    823     return mCurrentFrame.mdpCount;
    824 }
    825 
    826 bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
    827                                     hwc_display_contents_1_t* list) {
    828     if(isYuvPresent(ctx, mDpy)) {
    829         int nYuvCount = ctx->listStats[mDpy].yuvCount;
    830 
    831         for(int index = 0; index < nYuvCount ; index ++) {
    832             int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
    833 
    834             if(mCurrentFrame.isFBComposed[nYuvIndex])
    835                 continue;
    836 
    837             hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
    838 
    839             int mdpIndex = mCurrentFrame.layerToMDP[nYuvIndex];
    840 
    841             PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
    842             info.pipeInfo = new MdpPipeInfoLowRes;
    843             info.rot = NULL;
    844             MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
    845 
    846             pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
    847             if(pipe_info.index == ovutils::OV_INVALID) {
    848                 ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos",
    849                          __FUNCTION__);
    850                 return false;
    851             }
    852         }
    853     }
    854 
    855     for(int index = 0 ; index < mCurrentFrame.layerCount; index++ ) {
    856         if(mCurrentFrame.isFBComposed[index]) continue;
    857         hwc_layer_1_t* layer = &list->hwLayers[index];
    858         private_handle_t *hnd = (private_handle_t *)layer->handle;
    859 
    860         if(isYuvBuffer(hnd))
    861             continue;
    862 
    863         int mdpIndex = mCurrentFrame.layerToMDP[index];
    864 
    865         PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
    866         info.pipeInfo = new MdpPipeInfoLowRes;
    867         info.rot = NULL;
    868         MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
    869 
    870         ePipeType type = MDPCOMP_OV_ANY;
    871 
    872         if(!qhwc::needsScaling(layer) && !ctx->mNeedsRotator
    873            && ctx->mMDP.version >= qdutils::MDSS_V5) {
    874             type = MDPCOMP_OV_DMA;
    875         }
    876 
    877         pipe_info.index = getMdpPipe(ctx, type);
    878         if(pipe_info.index == ovutils::OV_INVALID) {
    879             ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
    880             return false;
    881         }
    882     }
    883     return true;
    884 }
    885 
    886 bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
    887 
    888     if(!isEnabled()) {
    889         ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
    890         return true;
    891     }
    892 
    893     if(!ctx || !list) {
    894         ALOGE("%s: invalid contxt or list",__FUNCTION__);
    895         return false;
    896     }
    897 
    898     /* reset Invalidator */
    899     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
    900         idleInvalidator->markForSleep();
    901 
    902     overlay::Overlay& ov = *ctx->mOverlay;
    903     LayerProp *layerProp = ctx->layerProp[mDpy];
    904 
    905     int numHwLayers = ctx->listStats[mDpy].numAppLayers;
    906     for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
    907     {
    908         if(mCurrentFrame.isFBComposed[i]) continue;
    909 
    910         hwc_layer_1_t *layer = &list->hwLayers[i];
    911         private_handle_t *hnd = (private_handle_t *)layer->handle;
    912         if(!hnd) {
    913             ALOGE("%s handle null", __FUNCTION__);
    914             return false;
    915         }
    916 
    917         int mdpIndex = mCurrentFrame.layerToMDP[i];
    918 
    919         MdpPipeInfoLowRes& pipe_info =
    920             *(MdpPipeInfoLowRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
    921         ovutils::eDest dest = pipe_info.index;
    922         if(dest == ovutils::OV_INVALID) {
    923             ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
    924             return false;
    925         }
    926 
    927         if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
    928             continue;
    929         }
    930 
    931         ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
    932                  using  pipe: %d", __FUNCTION__, layer,
    933                  hnd, dest );
    934 
    935         int fd = hnd->fd;
    936         uint32_t offset = hnd->offset;
    937         Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
    938         if(rot) {
    939             if(!rot->queueBuffer(fd, offset))
    940                 return false;
    941             fd = rot->getDstMemId();
    942             offset = rot->getDstOffset();
    943         }
    944 
    945         if (!ov.queueBuffer(fd, offset, dest)) {
    946             ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
    947             return false;
    948         }
    949 
    950         layerProp[i].mFlags &= ~HWC_MDPCOMP;
    951     }
    952     return true;
    953 }
    954 
    955 //=============MDPCompHighRes===================================================
    956 
    957 int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
    958                                 hwc_display_contents_1_t* list) {
    959     int pipesNeeded = 0;
    960     int hw_w = ctx->dpyAttr[mDpy].xres;
    961 
    962     for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
    963         if(!mCurrentFrame.isFBComposed[i]) {
    964             hwc_layer_1_t* layer = &list->hwLayers[i];
    965             hwc_rect_t dst = layer->displayFrame;
    966             if(dst.left > hw_w/2) {
    967                 pipesNeeded++;
    968             } else if(dst.right <= hw_w/2) {
    969                 pipesNeeded++;
    970             } else {
    971                 pipesNeeded += 2;
    972             }
    973         }
    974     }
    975     return pipesNeeded;
    976 }
    977 
    978 bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
    979                                      MdpPipeInfoHighRes& pipe_info,
    980                                      ePipeType type) {
    981     int hw_w = ctx->dpyAttr[mDpy].xres;
    982 
    983     hwc_rect_t dst = layer->displayFrame;
    984     if(dst.left > hw_w/2) {
    985         pipe_info.lIndex = ovutils::OV_INVALID;
    986         pipe_info.rIndex = getMdpPipe(ctx, type);
    987         if(pipe_info.rIndex == ovutils::OV_INVALID)
    988             return false;
    989     } else if (dst.right <= hw_w/2) {
    990         pipe_info.rIndex = ovutils::OV_INVALID;
    991         pipe_info.lIndex = getMdpPipe(ctx, type);
    992         if(pipe_info.lIndex == ovutils::OV_INVALID)
    993             return false;
    994     } else {
    995         pipe_info.rIndex = getMdpPipe(ctx, type);
    996         pipe_info.lIndex = getMdpPipe(ctx, type);
    997         if(pipe_info.rIndex == ovutils::OV_INVALID ||
    998            pipe_info.lIndex == ovutils::OV_INVALID)
    999             return false;
   1000     }
   1001     return true;
   1002 }
   1003 
   1004 bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx,
   1005                                      hwc_display_contents_1_t* list) {
   1006     overlay::Overlay& ov = *ctx->mOverlay;
   1007     int layer_count = ctx->listStats[mDpy].numAppLayers;
   1008 
   1009     if(isYuvPresent(ctx, mDpy)) {
   1010         int nYuvCount = ctx->listStats[mDpy].yuvCount;
   1011 
   1012         for(int index = 0; index < nYuvCount; index ++) {
   1013             int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
   1014             hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
   1015             PipeLayerPair& info = mCurrentFrame.mdpToLayer[nYuvIndex];
   1016             info.pipeInfo = new MdpPipeInfoHighRes;
   1017             info.rot = NULL;
   1018             MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
   1019             if(!acquireMDPPipes(ctx, layer, pipe_info,MDPCOMP_OV_VG)) {
   1020                 ALOGD_IF(isDebug(),"%s: Unable to get pipe for videos",
   1021                          __FUNCTION__);
   1022                 //TODO: windback pipebook data on fail
   1023                 return false;
   1024             }
   1025             pipe_info.zOrder = nYuvIndex;
   1026         }
   1027     }
   1028 
   1029     for(int index = 0 ; index < layer_count ; index++ ) {
   1030         hwc_layer_1_t* layer = &list->hwLayers[index];
   1031         private_handle_t *hnd = (private_handle_t *)layer->handle;
   1032 
   1033         if(isYuvBuffer(hnd))
   1034             continue;
   1035 
   1036         PipeLayerPair& info = mCurrentFrame.mdpToLayer[index];
   1037         info.pipeInfo = new MdpPipeInfoHighRes;
   1038         info.rot = NULL;
   1039         MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
   1040 
   1041         ePipeType type = MDPCOMP_OV_ANY;
   1042 
   1043         if(!qhwc::needsScaling(layer) && !ctx->mNeedsRotator
   1044            && ctx->mMDP.version >= qdutils::MDSS_V5)
   1045             type = MDPCOMP_OV_DMA;
   1046 
   1047         if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
   1048             ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__);
   1049             //TODO: windback pipebook data on fail
   1050             return false;
   1051         }
   1052         pipe_info.zOrder = index;
   1053     }
   1054     return true;
   1055 }
   1056 /*
   1057  * Configures pipe(s) for MDP composition
   1058  */
   1059 int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
   1060                               PipeLayerPair& PipeLayerPair) {
   1061     MdpPipeInfoHighRes& mdp_info =
   1062         *(static_cast<MdpPipeInfoHighRes*>(PipeLayerPair.pipeInfo));
   1063     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
   1064     eIsFg isFg = IS_FG_OFF;
   1065     eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
   1066     eDest lDest = mdp_info.lIndex;
   1067     eDest rDest = mdp_info.rIndex;
   1068 
   1069     ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
   1070              "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
   1071 
   1072     return configureHighRes(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg, lDest,
   1073                             rDest, &PipeLayerPair.rot);
   1074 }
   1075 
   1076 bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
   1077 
   1078     if(!isEnabled()) {
   1079         ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
   1080         return true;
   1081     }
   1082 
   1083     if(!ctx || !list) {
   1084         ALOGE("%s: invalid contxt or list",__FUNCTION__);
   1085         return false;
   1086     }
   1087 
   1088     /* reset Invalidator */
   1089     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
   1090         idleInvalidator->markForSleep();
   1091 
   1092     overlay::Overlay& ov = *ctx->mOverlay;
   1093     LayerProp *layerProp = ctx->layerProp[mDpy];
   1094 
   1095     int numHwLayers = ctx->listStats[mDpy].numAppLayers;
   1096     for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
   1097     {
   1098         if(mCurrentFrame.isFBComposed[i]) continue;
   1099 
   1100         hwc_layer_1_t *layer = &list->hwLayers[i];
   1101         private_handle_t *hnd = (private_handle_t *)layer->handle;
   1102         if(!hnd) {
   1103             ALOGE("%s handle null", __FUNCTION__);
   1104             return false;
   1105         }
   1106 
   1107         if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
   1108             continue;
   1109         }
   1110 
   1111         int mdpIndex = mCurrentFrame.layerToMDP[i];
   1112 
   1113         MdpPipeInfoHighRes& pipe_info =
   1114             *(MdpPipeInfoHighRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
   1115         Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
   1116 
   1117         ovutils::eDest indexL = pipe_info.lIndex;
   1118         ovutils::eDest indexR = pipe_info.rIndex;
   1119 
   1120         int fd = hnd->fd;
   1121         int offset = hnd->offset;
   1122 
   1123         if(rot) {
   1124             rot->queueBuffer(fd, offset);
   1125             fd = rot->getDstMemId();
   1126             offset = rot->getDstOffset();
   1127         }
   1128 
   1129         //************* play left mixer **********
   1130         if(indexL != ovutils::OV_INVALID) {
   1131             ovutils::eDest destL = (ovutils::eDest)indexL;
   1132             ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
   1133                      using  pipe: %d", __FUNCTION__, layer, hnd, indexL );
   1134             if (!ov.queueBuffer(fd, offset, destL)) {
   1135                 ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__);
   1136                 return false;
   1137             }
   1138         }
   1139 
   1140         //************* play right mixer **********
   1141         if(indexR != ovutils::OV_INVALID) {
   1142             ovutils::eDest destR = (ovutils::eDest)indexR;
   1143             ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
   1144                      using  pipe: %d", __FUNCTION__, layer, hnd, indexR );
   1145             if (!ov.queueBuffer(fd, offset, destR)) {
   1146                 ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__);
   1147                 return false;
   1148             }
   1149         }
   1150 
   1151         layerProp[i].mFlags &= ~HWC_MDPCOMP;
   1152     }
   1153 
   1154     return true;
   1155 }
   1156 }; //namespace
   1157 
   1158