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