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