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 "qdMetaData.h"
23#include "mdp_version.h"
24#include "hwc_fbupdate.h"
25#include "hwc_ad.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    if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
57        return;
58
59    dumpsys_log(buf,"HWC Map for Dpy: %s \n",
60                (mDpy == 0) ? "\"PRIMARY\"" :
61                (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
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    }
98
99    sEnableMixedMode = true;
100    if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
101       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
102        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
103        sEnableMixedMode = false;
104    }
105
106    sDebugLogs = false;
107    if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
108        if(atoi(property) != 0)
109            sDebugLogs = true;
110    }
111
112    sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
113    if(property_get("debug.mdpcomp.maxpermixer", property, "-1") > 0) {
114        int val = atoi(property);
115        if(val >= 0)
116            sMaxPipesPerMixer = min(val, MAX_PIPES_PER_MIXER);
117    }
118
119    if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
120        // Idle invalidation is not necessary on command mode panels
121        long idle_timeout = DEFAULT_IDLE_TIME;
122        if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
123            if(atoi(property) != 0)
124                idle_timeout = atoi(property);
125        }
126
127        //create Idle Invalidator only when not disabled through property
128        if(idle_timeout != -1)
129            idleInvalidator = IdleInvalidator::getInstance();
130
131        if(idleInvalidator == NULL) {
132            ALOGE("%s: failed to instantiate idleInvalidator object",
133                  __FUNCTION__);
134        } else {
135            idleInvalidator->init(timeout_handler, ctx, idle_timeout);
136        }
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        } else {
175            if(!mCurrentFrame.needsRedraw)
176                layer->compositionType = HWC_OVERLAY;
177        }
178    }
179}
180
181MDPComp::FrameInfo::FrameInfo() {
182    memset(&mdpToLayer, 0, sizeof(mdpToLayer));
183    reset(0);
184}
185
186void MDPComp::FrameInfo::reset(const int& numLayers) {
187    for(int i = 0 ; i < MAX_PIPES_PER_MIXER; i++ ) {
188        if(mdpToLayer[i].pipeInfo) {
189            delete mdpToLayer[i].pipeInfo;
190            mdpToLayer[i].pipeInfo = NULL;
191            //We dont own the rotator
192            mdpToLayer[i].rot = NULL;
193        }
194    }
195
196    memset(&mdpToLayer, 0, sizeof(mdpToLayer));
197    memset(&layerToMDP, -1, sizeof(layerToMDP));
198    memset(&isFBComposed, 1, sizeof(isFBComposed));
199
200    layerCount = numLayers;
201    fbCount = numLayers;
202    mdpCount = 0;
203    needsRedraw = true;
204    fbZ = 0;
205}
206
207void MDPComp::FrameInfo::map() {
208    // populate layer and MDP maps
209    int mdpIdx = 0;
210    for(int idx = 0; idx < layerCount; idx++) {
211        if(!isFBComposed[idx]) {
212            mdpToLayer[mdpIdx].listIndex = idx;
213            layerToMDP[idx] = mdpIdx++;
214        }
215    }
216}
217
218MDPComp::LayerCache::LayerCache() {
219    reset();
220}
221
222void MDPComp::LayerCache::reset() {
223    memset(&hnd, 0, sizeof(hnd));
224    mdpCount = 0;
225    fbCount = 0;
226    layerCount = 0;
227    fbZ = -1;
228}
229
230void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
231    const int numAppLayers = list->numHwLayers - 1;
232    for(int i = 0; i < numAppLayers; i++) {
233        hnd[i] = list->hwLayers[i].handle;
234    }
235}
236
237void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
238    mdpCount = curFrame.mdpCount;
239    fbCount = curFrame.fbCount;
240    layerCount = curFrame.layerCount;
241    fbZ = curFrame.fbZ;
242}
243
244bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
245    private_handle_t *hnd = (private_handle_t *)layer->handle;
246    if((not isYuvBuffer(hnd) and has90Transform(layer)) or
247        (not isValidDimension(ctx,layer))
248        //More conditions here, SKIP, sRGB+Blend etc
249        ) {
250        return false;
251    }
252    return true;
253}
254
255bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
256    const int dpy = HWC_DISPLAY_PRIMARY;
257    private_handle_t *hnd = (private_handle_t *)layer->handle;
258
259    if(!hnd) {
260        ALOGE("%s: layer handle is NULL", __FUNCTION__);
261        return false;
262    }
263
264    //XXX: Investigate doing this with pixel phase on MDSS
265    if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
266        return false;
267
268    int hw_w = ctx->dpyAttr[mDpy].xres;
269    int hw_h = ctx->dpyAttr[mDpy].yres;
270
271    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
272    hwc_rect_t dst = layer->displayFrame;
273
274    if(dst.left < 0 || dst.top < 0 || dst.right > hw_w || dst.bottom > hw_h) {
275       hwc_rect_t scissor = {0, 0, hw_w, hw_h };
276       qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
277    }
278
279    bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
280    int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
281    int crop_h = rotated90 ? crop.right - crop.left : 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            isSecondaryConnected(ctx)) {
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        if(mDpy > HWC_DISPLAY_PRIMARY && isL3SecureBuffer(hnd)) {
406            return false;
407        }
408
409        //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
410        // may not need it if Gfx pre-rotation can handle all flips & rotations
411        if(qdutils::MDPVersion::getInstance().is8x26() &&
412                                (ctx->dpyAttr[mDpy].xres > 1024) &&
413                                (layer->transform & HWC_TRANSFORM_FLIP_H) &&
414                                (!isYuvBuffer(hnd)))
415                   return false;
416    }
417
418    if(ctx->mAD->isDoable()) {
419        return false;
420    }
421
422    //If all above hard conditions are met we can do full or partial MDP comp.
423    bool ret = false;
424    if(fullMDPComp(ctx, list)) {
425        ret = true;
426    } else if(partialMDPComp(ctx, list)) {
427        ret = true;
428    }
429    return ret;
430}
431
432bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
433    //Will benefit presentation / secondary-only layer.
434    if((mDpy > HWC_DISPLAY_PRIMARY) &&
435            (list->numHwLayers - 1) > MAX_SEC_LAYERS) {
436        ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
437        return false;
438    }
439
440    /* XXX: There is some flicker currently seen with partial
441     * MDP composition on the virtual display.
442     * Disable UI MDP comp on virtual until it is fixed*/
443
444    if(mDpy > HWC_DISPLAY_EXTERNAL) {
445        return false;
446    }
447
448    const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
449    for(int i = 0; i < numAppLayers; i++) {
450        hwc_layer_1_t* layer = &list->hwLayers[i];
451        if(not isSupportedForMDPComp(ctx, layer)) {
452            ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
453            return false;
454        }
455    }
456
457    //Setup mCurrentFrame
458    mCurrentFrame.mdpCount = mCurrentFrame.layerCount;
459    mCurrentFrame.fbCount = 0;
460    mCurrentFrame.fbZ = -1;
461    memset(&mCurrentFrame.isFBComposed, 0, sizeof(mCurrentFrame.isFBComposed));
462
463    int mdpCount = mCurrentFrame.mdpCount;
464    if(mdpCount > sMaxPipesPerMixer) {
465        ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
466        return false;
467    }
468
469    if(!arePipesAvailable(ctx, list)) {
470        return false;
471    }
472
473    return true;
474}
475
476bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
477{
478    if(!sEnableMixedMode) {
479        //Mixed mode is disabled. No need to even try caching.
480        return false;
481    }
482
483    bool ret = false;
484    if(isLoadBasedCompDoable(ctx, list)) {
485        ret = loadBasedComp(ctx, list);
486    }
487
488    if(!ret) {
489        ret = cacheBasedComp(ctx, list);
490    }
491
492    return ret;
493}
494
495bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
496        hwc_display_contents_1_t* list) {
497    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
498    mCurrentFrame.reset(numAppLayers);
499    updateLayerCache(ctx, list);
500
501    //If an MDP marked layer is unsupported cannot do partial MDP Comp
502    for(int i = 0; i < numAppLayers; i++) {
503        if(!mCurrentFrame.isFBComposed[i]) {
504            hwc_layer_1_t* layer = &list->hwLayers[i];
505            if(not isSupportedForMDPComp(ctx, layer)) {
506                ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
507                        __FUNCTION__);
508                return false;
509            }
510        }
511    }
512
513    updateYUV(ctx, list);
514    bool ret = batchLayers(ctx, list); //sets up fbZ also
515    if(!ret) {
516        ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
517        return false;
518    }
519
520    int mdpCount = mCurrentFrame.mdpCount;
521
522    //Will benefit cases where a video has non-updating background.
523    if((mDpy > HWC_DISPLAY_PRIMARY) and
524            (mdpCount > MAX_SEC_LAYERS)) {
525        ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
526        return false;
527    }
528
529    /* XXX: There is some flicker currently seen with partial
530     * MDP composition on the virtual display.
531     * Disable UI MDP comp on virtual until it is fixed*/
532
533    if(mDpy > HWC_DISPLAY_EXTERNAL) {
534        return false;
535    }
536
537    if(mdpCount > (sMaxPipesPerMixer - 1)) { // -1 since FB is used
538        ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
539        return false;
540    }
541
542    if(!arePipesAvailable(ctx, list)) {
543        return false;
544    }
545
546    return true;
547}
548
549bool MDPComp::loadBasedComp(hwc_context_t *ctx,
550        hwc_display_contents_1_t* list) {
551    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
552    mCurrentFrame.reset(numAppLayers);
553
554    //TODO BatchSize could be optimized further based on available pipes, split
555    //displays etc.
556    const int batchSize = numAppLayers - (sMaxPipesPerMixer - 1);
557    if(batchSize <= 0) {
558        ALOGD_IF(isDebug(), "%s: Not attempting", __FUNCTION__);
559        return false;
560    }
561
562    int minBatchStart = -1;
563    size_t minBatchPixelCount = SIZE_MAX;
564
565    for(int i = 0; i <= numAppLayers - batchSize; i++) {
566        uint32_t batchPixelCount = 0;
567        for(int j = i; j < i + batchSize; j++) {
568            hwc_layer_1_t* layer = &list->hwLayers[j];
569            hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
570            batchPixelCount += (crop.right - crop.left) *
571                    (crop.bottom - crop.top);
572        }
573
574        if(batchPixelCount < minBatchPixelCount) {
575            minBatchPixelCount = batchPixelCount;
576            minBatchStart = i;
577        }
578    }
579
580    if(minBatchStart < 0) {
581        ALOGD_IF(isDebug(), "%s: No batch found batchSize %d numAppLayers %d",
582                __FUNCTION__, batchSize, numAppLayers);
583        return false;
584    }
585
586    for(int i = 0; i < numAppLayers; i++) {
587        if(i < minBatchStart || i >= minBatchStart + batchSize) {
588            hwc_layer_1_t* layer = &list->hwLayers[i];
589            if(not isSupportedForMDPComp(ctx, layer)) {
590                ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
591                        __FUNCTION__, i);
592                return false;
593            }
594            mCurrentFrame.isFBComposed[i] = false;
595        }
596    }
597
598    mCurrentFrame.fbZ = minBatchStart;
599    mCurrentFrame.fbCount = batchSize;
600    mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
601
602    if(!arePipesAvailable(ctx, list)) {
603        return false;
604    }
605
606    ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
607                __FUNCTION__, mCurrentFrame.fbZ, batchSize);
608    return true;
609}
610
611bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx,
612        hwc_display_contents_1_t* list) {
613    if(mDpy or isSecurePresent(ctx, mDpy) or
614            not (list->flags & HWC_GEOMETRY_CHANGED)) {
615        return false;
616    }
617    return true;
618}
619
620bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx,
621        hwc_display_contents_1_t* list){
622    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
623    mCurrentFrame.reset(numAppLayers);
624    updateYUV(ctx, list);
625    int mdpCount = mCurrentFrame.mdpCount;
626    int fbNeeded = int(mCurrentFrame.fbCount != 0);
627
628    if(!isYuvPresent(ctx, mDpy)) {
629        return false;
630    }
631
632    if(!mdpCount)
633        return false;
634
635    if(mdpCount > (sMaxPipesPerMixer - fbNeeded)) {
636        ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
637        return false;
638    }
639
640    if(!arePipesAvailable(ctx, list)) {
641        return false;
642    }
643
644    int nYuvCount = ctx->listStats[mDpy].yuvCount;
645    for(int index = 0; index < nYuvCount ; index ++) {
646        int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
647        hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
648        if(layer->planeAlpha < 0xFF) {
649            ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
650                    in video only mode",
651                    __FUNCTION__);
652            return false;
653        }
654        private_handle_t *hnd = (private_handle_t *)layer->handle;
655        if(mDpy > HWC_DISPLAY_PRIMARY && isL3SecureBuffer(hnd)) {
656            return false;
657        }
658    }
659
660    return true;
661}
662
663/* Checks for conditions where YUV layers cannot be bypassed */
664bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
665    if(isSkipLayer(layer)) {
666        ALOGE("%s: Unable to bypass skipped YUV", __FUNCTION__);
667        return false;
668    }
669
670    if(layer->transform & HWC_TRANSFORM_ROT_90 && !canUseRotator(ctx,mDpy)) {
671        ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
672        return false;
673    }
674
675    if(isSecuring(ctx, layer)) {
676        ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
677        return false;
678    }
679
680    if(!isValidDimension(ctx, layer)) {
681        ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
682            __FUNCTION__);
683        return false;
684    }
685
686    return true;
687}
688
689bool MDPComp::batchLayers(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
690    /* Idea is to keep as many contiguous non-updating(cached) layers in FB and
691     * send rest of them through MDP. NEVER mark an updating layer for caching.
692     * But cached ones can be marked for MDP*/
693
694    int maxBatchStart = -1;
695    int maxBatchCount = 0;
696
697    /* All or Nothing is cached. No batching needed */
698    if(!mCurrentFrame.fbCount) {
699        mCurrentFrame.fbZ = -1;
700        return true;
701    }
702    if(!mCurrentFrame.mdpCount) {
703        mCurrentFrame.fbZ = 0;
704        return true;
705    }
706
707    /* Search for max number of contiguous (cached) layers */
708    int i = 0;
709    while (i < mCurrentFrame.layerCount) {
710        int count = 0;
711        while(mCurrentFrame.isFBComposed[i] && i < mCurrentFrame.layerCount) {
712            count++; i++;
713        }
714        if(count > maxBatchCount) {
715            maxBatchCount = count;
716            maxBatchStart = i - count;
717            mCurrentFrame.fbZ = maxBatchStart;
718        }
719        if(i < mCurrentFrame.layerCount) i++;
720    }
721
722    /* reset rest of the layers for MDP comp */
723    for(int i = 0; i < mCurrentFrame.layerCount; i++) {
724        hwc_layer_1_t* layer = &list->hwLayers[i];
725        if(i != maxBatchStart) {
726            //If an unsupported layer is being attempted to be pulled out we
727            //should fail
728            if(not isSupportedForMDPComp(ctx, layer)) {
729                return false;
730            }
731            mCurrentFrame.isFBComposed[i] = false;
732        } else {
733            i += maxBatchCount;
734        }
735    }
736
737    mCurrentFrame.fbCount = maxBatchCount;
738    mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
739            mCurrentFrame.fbCount;
740
741    ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
742             mCurrentFrame.fbCount);
743
744    return true;
745}
746
747void MDPComp::updateLayerCache(hwc_context_t* ctx,
748        hwc_display_contents_1_t* list) {
749    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
750    int fbCount = 0;
751
752    for(int i = 0; i < numAppLayers; i++) {
753        hwc_layer_1_t* layer = &list->hwLayers[i];
754        if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
755            fbCount++;
756            mCurrentFrame.isFBComposed[i] = true;
757        } else {
758            mCurrentFrame.isFBComposed[i] = false;
759            mCachedFrame.hnd[i] = list->hwLayers[i].handle;
760        }
761    }
762
763    mCurrentFrame.fbCount = fbCount;
764    mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount;
765
766    ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d",__FUNCTION__,
767            mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
768}
769
770void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
771
772    int nYuvCount = ctx->listStats[mDpy].yuvCount;
773    for(int index = 0;index < nYuvCount; index++){
774        int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
775        hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
776
777        if(!isYUVDoable(ctx, layer)) {
778            if(!mCurrentFrame.isFBComposed[nYuvIndex]) {
779                mCurrentFrame.isFBComposed[nYuvIndex] = true;
780                mCurrentFrame.fbCount++;
781            }
782        } else {
783            if(mCurrentFrame.isFBComposed[nYuvIndex]) {
784                mCurrentFrame.isFBComposed[nYuvIndex] = false;
785                mCurrentFrame.fbCount--;
786            }
787        }
788    }
789
790    mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
791            mCurrentFrame.fbCount;
792    ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
793             mCurrentFrame.fbCount);
794}
795
796bool MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
797    if(!allocLayerPipes(ctx, list)) {
798        ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
799        return false;
800    }
801
802    bool fbBatch = false;
803    for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
804            index++) {
805        if(!mCurrentFrame.isFBComposed[index]) {
806            int mdpIndex = mCurrentFrame.layerToMDP[index];
807            hwc_layer_1_t* layer = &list->hwLayers[index];
808
809            MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
810            cur_pipe->zOrder = mdpNextZOrder++;
811
812            if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
813                ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
814                         layer %d",__FUNCTION__, index);
815                return false;
816            }
817        } else if(fbBatch == false) {
818                mdpNextZOrder++;
819                fbBatch = true;
820        }
821    }
822
823    return true;
824}
825
826bool MDPComp::programYUV(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
827    if(!allocLayerPipes(ctx, list)) {
828        ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
829        return false;
830    }
831    //If we are in this block, it means we have yuv + rgb layers both
832    int mdpIdx = 0;
833    for (int index = 0; index < mCurrentFrame.layerCount; index++) {
834        if(!mCurrentFrame.isFBComposed[index]) {
835            hwc_layer_1_t* layer = &list->hwLayers[index];
836            int mdpIndex = mCurrentFrame.layerToMDP[index];
837            MdpPipeInfo* cur_pipe =
838                    mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
839            cur_pipe->zOrder = mdpIdx++;
840
841            if(configure(ctx, layer,
842                        mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
843                ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
844                        layer %d",__FUNCTION__, index);
845                return false;
846            }
847        }
848    }
849    return true;
850}
851
852int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
853    const int numLayers = ctx->listStats[mDpy].numAppLayers;
854
855    //reset old data
856    mCurrentFrame.reset(numLayers);
857
858    //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
859    //do not cache the information for next draw cycle.
860    if(numLayers > MAX_NUM_APP_LAYERS) {
861        mCachedFrame.updateCounts(mCurrentFrame);
862        ALOGD_IF(isDebug(), "%s: Number of App layers exceeded the limit ",
863                __FUNCTION__);
864        return -1;
865    }
866
867    //Hard conditions, if not met, cannot do MDP comp
868    if(!isFrameDoable(ctx)) {
869        ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
870                __FUNCTION__);
871        reset(numLayers, list);
872        return -1;
873    }
874
875    //Check whether layers marked for MDP Composition is actually doable.
876    if(isFullFrameDoable(ctx, list)) {
877        mCurrentFrame.map();
878        //Configure framebuffer first if applicable
879        if(mCurrentFrame.fbZ >= 0) {
880            if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list,
881                        mCurrentFrame.fbZ)) {
882                ALOGE("%s configure framebuffer failed", __func__);
883                reset(numLayers, list);
884                return -1;
885            }
886        }
887        //Acquire and Program MDP pipes
888        if(!programMDP(ctx, list)) {
889            reset(numLayers, list);
890            return -1;
891        } else { //Success
892            //Any change in composition types needs an FB refresh
893            mCurrentFrame.needsRedraw = false;
894            if(mCurrentFrame.fbCount &&
895                    ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) ||
896                     (mCurrentFrame.fbCount != mCachedFrame.fbCount) ||
897                     (mCurrentFrame.fbZ != mCachedFrame.fbZ) ||
898                     (!mCurrentFrame.mdpCount) ||
899                     (list->flags & HWC_GEOMETRY_CHANGED) ||
900                     isSkipPresent(ctx, mDpy))) {
901                mCurrentFrame.needsRedraw = true;
902            }
903        }
904    } else if(isOnlyVideoDoable(ctx, list)) {
905        //All layers marked for MDP comp cannot be bypassed.
906        //Try to compose atleast YUV layers through MDP comp and let
907        //all the RGB layers compose in FB
908        //Destination over
909        mCurrentFrame.fbZ = -1;
910        if(mCurrentFrame.fbCount)
911            mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
912
913        mCurrentFrame.map();
914
915        //Configure framebuffer first if applicable
916        if(mCurrentFrame.fbZ >= 0) {
917            if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
918                ALOGE("%s configure framebuffer failed", __func__);
919                reset(numLayers, list);
920                return -1;
921            }
922        }
923        if(!programYUV(ctx, list)) {
924            reset(numLayers, list);
925            return -1;
926        }
927    } else {
928        reset(numLayers, list);
929        return -1;
930    }
931
932    //UpdateLayerFlags
933    setMDPCompLayerFlags(ctx, list);
934    mCachedFrame.updateCounts(mCurrentFrame);
935
936    // unlock it before calling dump function to avoid deadlock
937    if(isDebug()) {
938        ALOGD("GEOMETRY change: %d", (list->flags & HWC_GEOMETRY_CHANGED));
939        android::String8 sDump("");
940        dump(sDump);
941        ALOGE("%s",sDump.string());
942    }
943
944    return 0;
945}
946
947//=============MDPCompLowRes===================================================
948
949/*
950 * Configures pipe(s) for MDP composition
951 */
952int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
953                             PipeLayerPair& PipeLayerPair) {
954    MdpPipeInfoLowRes& mdp_info =
955        *(static_cast<MdpPipeInfoLowRes*>(PipeLayerPair.pipeInfo));
956    eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
957    eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
958    eIsFg isFg = IS_FG_OFF;
959    eDest dest = mdp_info.index;
960
961    ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
962             __FUNCTION__, layer, zOrder, dest);
963
964    return configureLowRes(ctx, layer, mDpy, mdpFlags, zOrder, isFg, dest,
965                           &PipeLayerPair.rot);
966}
967
968bool MDPCompLowRes::arePipesAvailable(hwc_context_t *ctx,
969        hwc_display_contents_1_t* list) {
970    overlay::Overlay& ov = *ctx->mOverlay;
971    int numPipesNeeded = mCurrentFrame.mdpCount;
972    int availPipes = ov.availablePipes(mDpy, Overlay::MIXER_DEFAULT);
973
974    //Reserve pipe for FB
975    if(mCurrentFrame.fbCount)
976        availPipes -= 1;
977
978    if(numPipesNeeded > availPipes) {
979        ALOGD_IF(isDebug(), "%s: Insufficient pipes, dpy %d needed %d, avail %d",
980                __FUNCTION__, mDpy, numPipesNeeded, availPipes);
981        return false;
982    }
983
984    return true;
985}
986
987bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
988        hwc_display_contents_1_t* list) {
989    for(int index = 0; index < mCurrentFrame.layerCount; index++) {
990
991        if(mCurrentFrame.isFBComposed[index]) continue;
992
993        hwc_layer_1_t* layer = &list->hwLayers[index];
994        private_handle_t *hnd = (private_handle_t *)layer->handle;
995        int mdpIndex = mCurrentFrame.layerToMDP[index];
996        PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
997        info.pipeInfo = new MdpPipeInfoLowRes;
998        info.rot = NULL;
999        MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo;
1000        ePipeType type = MDPCOMP_OV_ANY;
1001
1002        if(isYuvBuffer(hnd)) {
1003            type = MDPCOMP_OV_VG;
1004        } else if(!qhwc::needsScaling(ctx, layer, mDpy)
1005            && Overlay::getDMAMode() != Overlay::DMA_BLOCK_MODE
1006            && ctx->mMDP.version >= qdutils::MDSS_V5) {
1007            type = MDPCOMP_OV_DMA;
1008        }
1009
1010        pipe_info.index = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
1011        if(pipe_info.index == ovutils::OV_INVALID) {
1012            ALOGD_IF(isDebug(), "%s: Unable to get pipe type = %d",
1013                __FUNCTION__, (int) type);
1014            return false;
1015        }
1016    }
1017    return true;
1018}
1019
1020bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
1021
1022    if(!isEnabled()) {
1023        ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
1024        return true;
1025    }
1026
1027    if(!ctx || !list) {
1028        ALOGE("%s: invalid contxt or list",__FUNCTION__);
1029        return false;
1030    }
1031
1032    if(ctx->listStats[mDpy].numAppLayers > MAX_NUM_APP_LAYERS) {
1033        ALOGD_IF(isDebug(),"%s: Exceeding max layer count", __FUNCTION__);
1034        return true;
1035    }
1036
1037    /* reset Invalidator */
1038    if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
1039        idleInvalidator->markForSleep();
1040
1041    overlay::Overlay& ov = *ctx->mOverlay;
1042    LayerProp *layerProp = ctx->layerProp[mDpy];
1043
1044    int numHwLayers = ctx->listStats[mDpy].numAppLayers;
1045    for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
1046    {
1047        if(mCurrentFrame.isFBComposed[i]) continue;
1048
1049        hwc_layer_1_t *layer = &list->hwLayers[i];
1050        private_handle_t *hnd = (private_handle_t *)layer->handle;
1051        if(!hnd) {
1052            ALOGE("%s handle null", __FUNCTION__);
1053            return false;
1054        }
1055
1056        int mdpIndex = mCurrentFrame.layerToMDP[i];
1057
1058        MdpPipeInfoLowRes& pipe_info =
1059            *(MdpPipeInfoLowRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1060        ovutils::eDest dest = pipe_info.index;
1061        if(dest == ovutils::OV_INVALID) {
1062            ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
1063            return false;
1064        }
1065
1066        if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
1067            continue;
1068        }
1069
1070        ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
1071                 using  pipe: %d", __FUNCTION__, layer,
1072                 hnd, dest );
1073
1074        int fd = hnd->fd;
1075        uint32_t offset = hnd->offset;
1076
1077        if(ctx->mAD->isModeOn()) {
1078            if(ctx->mAD->draw(ctx, fd, offset)) {
1079                fd = ctx->mAD->getDstFd(ctx);
1080                offset = ctx->mAD->getDstOffset(ctx);
1081            }
1082        }
1083
1084        Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
1085        if(rot) {
1086            if(!rot->queueBuffer(fd, offset))
1087                return false;
1088            fd = rot->getDstMemId();
1089            offset = rot->getDstOffset();
1090        }
1091
1092        if (!ov.queueBuffer(fd, offset, dest)) {
1093            ALOGE("%s: queueBuffer failed for display:%d ", __FUNCTION__, mDpy);
1094            return false;
1095        }
1096
1097        layerProp[i].mFlags &= ~HWC_MDPCOMP;
1098    }
1099    return true;
1100}
1101
1102//=============MDPCompHighRes===================================================
1103
1104int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
1105        hwc_display_contents_1_t* list,
1106        int mixer) {
1107    int pipesNeeded = 0;
1108    const int xres = ctx->dpyAttr[mDpy].xres;
1109
1110    const int lSplit = getLeftSplit(ctx, mDpy);
1111
1112    for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
1113        if(!mCurrentFrame.isFBComposed[i]) {
1114            hwc_layer_1_t* layer = &list->hwLayers[i];
1115            hwc_rect_t dst = layer->displayFrame;
1116            if(mixer == Overlay::MIXER_LEFT && dst.left < lSplit) {
1117                pipesNeeded++;
1118            } else if(mixer == Overlay::MIXER_RIGHT && dst.right > lSplit) {
1119                pipesNeeded++;
1120            }
1121        }
1122    }
1123    return pipesNeeded;
1124}
1125
1126bool MDPCompHighRes::arePipesAvailable(hwc_context_t *ctx,
1127        hwc_display_contents_1_t* list) {
1128    overlay::Overlay& ov = *ctx->mOverlay;
1129
1130    for(int i = 0; i < Overlay::MIXER_MAX; i++) {
1131        int numPipesNeeded = pipesNeeded(ctx, list, i);
1132        int availPipes = ov.availablePipes(mDpy, i);
1133
1134        //Reserve pipe(s)for FB
1135        if(mCurrentFrame.fbCount)
1136            availPipes -= 1;
1137
1138        if(numPipesNeeded > availPipes) {
1139            ALOGD_IF(isDebug(), "%s: Insufficient pipes for "
1140                     "dpy %d mixer %d needed %d, avail %d",
1141                     __FUNCTION__, mDpy, i, numPipesNeeded, availPipes);
1142            return false;
1143        }
1144    }
1145    return true;
1146}
1147
1148bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
1149        MdpPipeInfoHighRes& pipe_info,
1150        ePipeType type) {
1151    const int xres = ctx->dpyAttr[mDpy].xres;
1152    const int lSplit = getLeftSplit(ctx, mDpy);
1153
1154    hwc_rect_t dst = layer->displayFrame;
1155    pipe_info.lIndex = ovutils::OV_INVALID;
1156    pipe_info.rIndex = ovutils::OV_INVALID;
1157
1158    if (dst.left < lSplit) {
1159        pipe_info.lIndex = getMdpPipe(ctx, type, Overlay::MIXER_LEFT);
1160        if(pipe_info.lIndex == ovutils::OV_INVALID)
1161            return false;
1162    }
1163
1164    if(dst.right > lSplit) {
1165        pipe_info.rIndex = getMdpPipe(ctx, type, Overlay::MIXER_RIGHT);
1166        if(pipe_info.rIndex == ovutils::OV_INVALID)
1167            return false;
1168    }
1169
1170    return true;
1171}
1172
1173bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx,
1174        hwc_display_contents_1_t* list) {
1175    for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
1176
1177        if(mCurrentFrame.isFBComposed[index]) continue;
1178
1179        hwc_layer_1_t* layer = &list->hwLayers[index];
1180        private_handle_t *hnd = (private_handle_t *)layer->handle;
1181        int mdpIndex = mCurrentFrame.layerToMDP[index];
1182        PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
1183        info.pipeInfo = new MdpPipeInfoHighRes;
1184        info.rot = NULL;
1185        MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo;
1186        ePipeType type = MDPCOMP_OV_ANY;
1187
1188        if(isYuvBuffer(hnd)) {
1189            type = MDPCOMP_OV_VG;
1190        } else if(!qhwc::needsScaling(ctx, layer, mDpy)
1191            && Overlay::getDMAMode() != Overlay::DMA_BLOCK_MODE
1192            && ctx->mMDP.version >= qdutils::MDSS_V5) {
1193            type = MDPCOMP_OV_DMA;
1194        }
1195
1196        if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
1197            ALOGD_IF(isDebug(), "%s: Unable to get pipe for type = %d",
1198                    __FUNCTION__, (int) type);
1199            return false;
1200        }
1201    }
1202    return true;
1203}
1204
1205/*
1206 * Configures pipe(s) for MDP composition
1207 */
1208int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
1209        PipeLayerPair& PipeLayerPair) {
1210    MdpPipeInfoHighRes& mdp_info =
1211        *(static_cast<MdpPipeInfoHighRes*>(PipeLayerPair.pipeInfo));
1212    eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
1213    eIsFg isFg = IS_FG_OFF;
1214    eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
1215    eDest lDest = mdp_info.lIndex;
1216    eDest rDest = mdp_info.rIndex;
1217
1218    ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
1219             "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
1220
1221    return configureHighRes(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg, lDest,
1222                            rDest, &PipeLayerPair.rot);
1223}
1224
1225bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
1226
1227    if(!isEnabled()) {
1228        ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
1229        return true;
1230    }
1231
1232    if(!ctx || !list) {
1233        ALOGE("%s: invalid contxt or list",__FUNCTION__);
1234        return false;
1235    }
1236
1237    if(ctx->listStats[mDpy].numAppLayers > MAX_NUM_APP_LAYERS) {
1238        ALOGD_IF(isDebug(),"%s: Exceeding max layer count", __FUNCTION__);
1239        return true;
1240    }
1241
1242    /* reset Invalidator */
1243    if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
1244        idleInvalidator->markForSleep();
1245
1246    overlay::Overlay& ov = *ctx->mOverlay;
1247    LayerProp *layerProp = ctx->layerProp[mDpy];
1248
1249    int numHwLayers = ctx->listStats[mDpy].numAppLayers;
1250    for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
1251    {
1252        if(mCurrentFrame.isFBComposed[i]) continue;
1253
1254        hwc_layer_1_t *layer = &list->hwLayers[i];
1255        private_handle_t *hnd = (private_handle_t *)layer->handle;
1256        if(!hnd) {
1257            ALOGE("%s handle null", __FUNCTION__);
1258            return false;
1259        }
1260
1261        if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
1262            continue;
1263        }
1264
1265        int mdpIndex = mCurrentFrame.layerToMDP[i];
1266
1267        MdpPipeInfoHighRes& pipe_info =
1268            *(MdpPipeInfoHighRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
1269        Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
1270
1271        ovutils::eDest indexL = pipe_info.lIndex;
1272        ovutils::eDest indexR = pipe_info.rIndex;
1273
1274        int fd = hnd->fd;
1275        int offset = hnd->offset;
1276
1277        if(ctx->mAD->isModeOn()) {
1278            if(ctx->mAD->draw(ctx, fd, offset)) {
1279                fd = ctx->mAD->getDstFd(ctx);
1280                offset = ctx->mAD->getDstOffset(ctx);
1281            }
1282        }
1283
1284        if(rot) {
1285            rot->queueBuffer(fd, offset);
1286            fd = rot->getDstMemId();
1287            offset = rot->getDstOffset();
1288        }
1289
1290        //************* play left mixer **********
1291        if(indexL != ovutils::OV_INVALID) {
1292            ovutils::eDest destL = (ovutils::eDest)indexL;
1293            ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
1294                     using  pipe: %d", __FUNCTION__, layer, hnd, indexL );
1295            if (!ov.queueBuffer(fd, offset, destL)) {
1296                ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__);
1297                return false;
1298            }
1299        }
1300
1301        //************* play right mixer **********
1302        if(indexR != ovutils::OV_INVALID) {
1303            ovutils::eDest destR = (ovutils::eDest)indexR;
1304            ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
1305                     using  pipe: %d", __FUNCTION__, layer, hnd, indexR );
1306            if (!ov.queueBuffer(fd, offset, destR)) {
1307                ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__);
1308                return false;
1309            }
1310        }
1311
1312        layerProp[i].mFlags &= ~HWC_MDPCOMP;
1313    }
1314
1315    return true;
1316}
1317}; //namespace
1318
1319