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