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