hwc_utils.cpp revision b434b98715e4bfe9b8bfb0ac34f33e695aa9891d
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012-2013, The Linux Foundation All rights reserved.
4 *
5 * Not a Contribution, Apache license notifications and license are retained
6 * for attribution purposes only.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
21#define HWC_UTILS_DEBUG 0
22#include <math.h>
23#include <sys/ioctl.h>
24#include <binder/IServiceManager.h>
25#include <EGL/egl.h>
26#include <cutils/properties.h>
27#include <utils/Trace.h>
28#include <gralloc_priv.h>
29#include <overlay.h>
30#include <overlayRotator.h>
31#include <overlayWriteback.h>
32#include "hwc_utils.h"
33#include "hwc_mdpcomp.h"
34#include "hwc_fbupdate.h"
35#include "hwc_ad.h"
36#include "mdp_version.h"
37#include "hwc_copybit.h"
38#include "external.h"
39#include "hwc_qclient.h"
40#include "QService.h"
41#include "comptype.h"
42
43using namespace qClient;
44using namespace qService;
45using namespace android;
46using namespace overlay;
47using namespace overlay::utils;
48namespace ovutils = overlay::utils;
49
50namespace qhwc {
51
52static int openFramebufferDevice(hwc_context_t *ctx)
53{
54    struct fb_fix_screeninfo finfo;
55    struct fb_var_screeninfo info;
56
57    int fb_fd = openFb(HWC_DISPLAY_PRIMARY);
58    if(fb_fd < 0) {
59        ALOGE("%s: Error Opening FB : %s", __FUNCTION__, strerror(errno));
60        return -errno;
61    }
62
63    if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &info) == -1) {
64        ALOGE("%s:Error in ioctl FBIOGET_VSCREENINFO: %s", __FUNCTION__,
65                                                       strerror(errno));
66        close(fb_fd);
67        return -errno;
68    }
69
70    if (int(info.width) <= 0 || int(info.height) <= 0) {
71        // the driver doesn't return that information
72        // default to 160 dpi
73        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
74        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
75    }
76
77    float xdpi = (info.xres * 25.4f) / info.width;
78    float ydpi = (info.yres * 25.4f) / info.height;
79
80#ifdef MSMFB_METADATA_GET
81    struct msmfb_metadata metadata;
82    memset(&metadata, 0 , sizeof(metadata));
83    metadata.op = metadata_op_frame_rate;
84
85    if (ioctl(fb_fd, MSMFB_METADATA_GET, &metadata) == -1) {
86        ALOGE("%s:Error retrieving panel frame rate: %s", __FUNCTION__,
87                                                      strerror(errno));
88        close(fb_fd);
89        return -errno;
90    }
91
92    float fps  = metadata.data.panel_frame_rate;
93#else
94    //XXX: Remove reserved field usage on all baselines
95    //The reserved[3] field is used to store FPS by the driver.
96    float fps  = info.reserved[3] & 0xFF;
97#endif
98
99    if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
100        ALOGE("%s:Error in ioctl FBIOGET_FSCREENINFO: %s", __FUNCTION__,
101                                                       strerror(errno));
102        close(fb_fd);
103        return -errno;
104    }
105
106    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = fb_fd;
107    //xres, yres may not be 32 aligned
108    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].stride = finfo.line_length /(info.xres/8);
109    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = info.xres;
110    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres;
111    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
112    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
113    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period = 1000000000l / fps;
114
115    //Unblank primary on first boot
116    if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
117        ALOGE("%s: Failed to unblank display", __FUNCTION__);
118        return -errno;
119    }
120    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive = true;
121
122    return 0;
123}
124
125void initContext(hwc_context_t *ctx)
126{
127    memset(&ctx->dpyAttr, 0, sizeof(ctx->dpyAttr));
128    if(openFramebufferDevice(ctx) < 0) {
129        ALOGE("%s: failed to open framebuffer!!", __FUNCTION__);
130    }
131
132    overlay::Overlay::initOverlay();
133    ctx->mOverlay = overlay::Overlay::getInstance();
134    ctx->mRotMgr = new RotMgr();
135    ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
136    ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
137    ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
138    const int rightSplit = qdutils::MDPVersion::getInstance().getRightSplit();
139    overlay::Overlay::initOverlay();
140    ctx->mOverlay = overlay::Overlay::getInstance();
141    ctx->mRotMgr = new RotMgr();
142
143    //Is created and destroyed only once for primary
144    //For external it could get created and destroyed multiple times depending
145    //on what external we connect to.
146    ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
147        IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
148                rightSplit, HWC_DISPLAY_PRIMARY);
149
150    // Check if the target supports copybit compostion (dyn/mdp/c2d) to
151    // decide if we need to open the copybit module.
152    int compositionType =
153        qdutils::QCCompositionType::getInstance().getCompositionType();
154
155    if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
156                           qdutils::COMPOSITION_TYPE_MDP |
157                           qdutils::COMPOSITION_TYPE_C2D)) {
158            ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit();
159    }
160
161    ctx->mExtDisplay = new ExternalDisplay(ctx);
162
163    for (uint32_t i = 0; i < MAX_DISPLAYS; i++) {
164        ctx->mLayerRotMap[i] = new LayerRotMap();
165    }
166
167    ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
168         MDPComp::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
169                rightSplit, HWC_DISPLAY_PRIMARY);
170
171    MDPComp::init(ctx);
172    ctx->mAD = new AssertiveDisplay();
173
174    ctx->vstate.enable = false;
175    ctx->vstate.fakevsync = false;
176
177    //Right now hwc starts the service but anybody could do it, or it could be
178    //independent process as well.
179    QService::init();
180    sp<IQClient> client = new QClient(ctx);
181    interface_cast<IQService>(
182            defaultServiceManager()->getService(
183            String16("display.qservice")))->connect(client);
184
185    ALOGI("Initializing Qualcomm Hardware Composer");
186    ALOGI("MDP version: %d", ctx->mMDP.version);
187}
188
189void closeContext(hwc_context_t *ctx)
190{
191    if(ctx->mOverlay) {
192        delete ctx->mOverlay;
193        ctx->mOverlay = NULL;
194    }
195
196    if(ctx->mRotMgr) {
197        delete ctx->mRotMgr;
198        ctx->mRotMgr = NULL;
199    }
200
201    for(int i = 0; i < MAX_DISPLAYS; i++) {
202        if(ctx->mCopyBit[i]) {
203            delete ctx->mCopyBit[i];
204            ctx->mCopyBit[i] = NULL;
205        }
206    }
207
208    if(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd) {
209        close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd);
210        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1;
211    }
212
213    if(ctx->mExtDisplay) {
214        delete ctx->mExtDisplay;
215        ctx->mExtDisplay = NULL;
216    }
217
218    for(int i = 0; i < MAX_DISPLAYS; i++) {
219        if(ctx->mFBUpdate[i]) {
220            delete ctx->mFBUpdate[i];
221            ctx->mFBUpdate[i] = NULL;
222        }
223        if(ctx->mMDPComp[i]) {
224            delete ctx->mMDPComp[i];
225            ctx->mMDPComp[i] = NULL;
226        }
227        if(ctx->mLayerRotMap[i]) {
228            delete ctx->mLayerRotMap[i];
229            ctx->mLayerRotMap[i] = NULL;
230        }
231    }
232
233    if(ctx->mAD) {
234        delete ctx->mAD;
235        ctx->mAD = NULL;
236    }
237}
238
239
240void dumpsys_log(android::String8& buf, const char* fmt, ...)
241{
242    va_list varargs;
243    va_start(varargs, fmt);
244    buf.appendFormatV(fmt, varargs);
245    va_end(varargs);
246}
247
248/* Calculates the destination position based on the action safe rectangle */
249void getActionSafePosition(hwc_context_t *ctx, int dpy, uint32_t& x,
250                           uint32_t& y, uint32_t& w, uint32_t& h) {
251
252    // if external supports underscan, do nothing
253    // it will be taken care in the driver
254    if(ctx->mExtDisplay->isCEUnderscanSupported())
255        return;
256
257    char value[PROPERTY_VALUE_MAX];
258    // Read action safe properties
259    property_get("persist.sys.actionsafe.width", value, "0");
260    int asWidthRatio = atoi(value);
261    property_get("persist.sys.actionsafe.height", value, "0");
262    int asHeightRatio = atoi(value);
263
264    if(!asWidthRatio && !asHeightRatio) {
265        //No action safe ratio set, return
266        return;
267    }
268
269    float wRatio = 1.0;
270    float hRatio = 1.0;
271    float xRatio = 1.0;
272    float yRatio = 1.0;
273
274    float fbWidth = ctx->dpyAttr[dpy].xres;
275    float fbHeight = ctx->dpyAttr[dpy].yres;
276
277    float asX = 0;
278    float asY = 0;
279    float asW = fbWidth;
280    float asH= fbHeight;
281
282    // based on the action safe ratio, get the Action safe rectangle
283    asW = fbWidth * (1.0f -  asWidthRatio / 100.0f);
284    asH = fbHeight * (1.0f -  asHeightRatio / 100.0f);
285    asX = (fbWidth - asW) / 2;
286    asY = (fbHeight - asH) / 2;
287
288    // calculate the position ratio
289    xRatio = (float)x/fbWidth;
290    yRatio = (float)y/fbHeight;
291    wRatio = (float)w/fbWidth;
292    hRatio = (float)h/fbHeight;
293
294    //Calculate the position...
295    x = (xRatio * asW) + asX;
296    y = (yRatio * asH) + asY;
297    w = (wRatio * asW);
298    h = (hRatio * asH);
299
300    return;
301}
302
303bool needsScaling(hwc_context_t* ctx, hwc_layer_1_t const* layer,
304        const int& dpy) {
305    int dst_w, dst_h, src_w, src_h;
306
307    hwc_rect_t displayFrame  = layer->displayFrame;
308    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
309    trimLayer(ctx, dpy, layer->transform, sourceCrop, displayFrame);
310
311    dst_w = displayFrame.right - displayFrame.left;
312    dst_h = displayFrame.bottom - displayFrame.top;
313    src_w = sourceCrop.right - sourceCrop.left;
314    src_h = sourceCrop.bottom - sourceCrop.top;
315
316    if(((src_w != dst_w) || (src_h != dst_h)))
317        return true;
318
319    return false;
320}
321
322bool isAlphaScaled(hwc_context_t* ctx, hwc_layer_1_t const* layer,
323        const int& dpy) {
324    if(needsScaling(ctx, layer, dpy) && isAlphaPresent(layer)) {
325        return true;
326    }
327    return false;
328}
329
330bool isAlphaPresent(hwc_layer_1_t const* layer) {
331    private_handle_t *hnd = (private_handle_t *)layer->handle;
332    if(hnd) {
333        int format = hnd->format;
334        switch(format) {
335        case HAL_PIXEL_FORMAT_RGBA_8888:
336        case HAL_PIXEL_FORMAT_BGRA_8888:
337            // In any more formats with Alpha go here..
338            return true;
339        default : return false;
340        }
341    }
342    return false;
343}
344
345// Let CABL know we have a YUV layer
346static void setYUVProp(int yuvCount) {
347    static char property[PROPERTY_VALUE_MAX];
348    if(yuvCount > 0) {
349        if (property_get("hw.cabl.yuv", property, NULL) > 0) {
350            if (atoi(property) != 1) {
351                property_set("hw.cabl.yuv", "1");
352            }
353        }
354    } else {
355        if (property_get("hw.cabl.yuv", property, NULL) > 0) {
356            if (atoi(property) != 0) {
357                property_set("hw.cabl.yuv", "0");
358            }
359        }
360    }
361}
362
363void setListStats(hwc_context_t *ctx,
364        const hwc_display_contents_1_t *list, int dpy) {
365    const int prevYuvCount = ctx->listStats[dpy].yuvCount;
366    memset(&ctx->listStats[dpy], 0, sizeof(ListStats));
367    ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
368    ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
369    ctx->listStats[dpy].skipCount = 0;
370    ctx->listStats[dpy].needsAlphaScale = false;
371    ctx->listStats[dpy].preMultipliedAlpha = false;
372    ctx->listStats[dpy].planeAlpha = false;
373    ctx->listStats[dpy].isSecurePresent = false;
374    ctx->listStats[dpy].yuvCount = 0;
375
376    for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
377        hwc_layer_1_t const* layer = &list->hwLayers[i];
378        private_handle_t *hnd = (private_handle_t *)layer->handle;
379
380        // continue if number of app layers exceeds MAX_NUM_APP_LAYERS
381        if(ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS)
382            continue;
383
384        //reset yuv indices
385        ctx->listStats[dpy].yuvIndices[i] = -1;
386
387        if (isSecureBuffer(hnd)) {
388            ctx->listStats[dpy].isSecurePresent = true;
389        }
390
391        if (isSkipLayer(&list->hwLayers[i])) {
392            ctx->listStats[dpy].skipCount++;
393        } else if (UNLIKELY(isYuvBuffer(hnd))) {
394            int& yuvCount = ctx->listStats[dpy].yuvCount;
395            ctx->listStats[dpy].yuvIndices[yuvCount] = i;
396            yuvCount++;
397
398            if((layer->transform & HWC_TRANSFORM_ROT_90) &&
399                    canUseRotator(ctx, dpy)) {
400                if( (dpy == HWC_DISPLAY_PRIMARY) &&
401                        ctx->mOverlay->isPipeTypeAttached(OV_MDP_PIPE_DMA)) {
402                    ctx->isPaddingRound = true;
403                }
404                Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
405            }
406        }
407        if(layer->blending == HWC_BLENDING_PREMULT)
408            ctx->listStats[dpy].preMultipliedAlpha = true;
409        if(layer->planeAlpha < 0xFF)
410            ctx->listStats[dpy].planeAlpha = true;
411        if(!ctx->listStats[dpy].needsAlphaScale)
412            ctx->listStats[dpy].needsAlphaScale =
413                    isAlphaScaled(ctx, layer, dpy);
414    }
415    setYUVProp(ctx->listStats[dpy].yuvCount);
416    //The marking of video begin/end is useful on some targets where we need
417    //to have a padding round to be able to shift pipes across mixers.
418    if(prevYuvCount != ctx->listStats[dpy].yuvCount) {
419        ctx->mVideoTransFlag = true;
420    }
421    if(dpy == HWC_DISPLAY_PRIMARY) {
422        ctx->mAD->markDoable(ctx, list);
423    }
424}
425
426
427static void calc_cut(double& leftCutRatio, double& topCutRatio,
428        double& rightCutRatio, double& bottomCutRatio, int orient) {
429    if(orient & HAL_TRANSFORM_FLIP_H) {
430        swap(leftCutRatio, rightCutRatio);
431    }
432    if(orient & HAL_TRANSFORM_FLIP_V) {
433        swap(topCutRatio, bottomCutRatio);
434    }
435    if(orient & HAL_TRANSFORM_ROT_90) {
436        //Anti clock swapping
437        double tmpCutRatio = leftCutRatio;
438        leftCutRatio = topCutRatio;
439        topCutRatio = rightCutRatio;
440        rightCutRatio = bottomCutRatio;
441        bottomCutRatio = tmpCutRatio;
442    }
443}
444
445bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer) {
446    if((ctx->mMDP.version < qdutils::MDSS_V5) &&
447       (ctx->mMDP.version > qdutils::MDP_V3_0) &&
448        ctx->mSecuring) {
449        return true;
450    }
451    //  On A-Family, Secure policy is applied system wide and not on
452    //  buffers.
453    if (isSecureModePolicy(ctx->mMDP.version)) {
454        private_handle_t *hnd = (private_handle_t *)layer->handle;
455        if(ctx->mSecureMode) {
456            if (! isSecureBuffer(hnd)) {
457                // This code path executes for the following usecase:
458                // Some Apps in which first few seconds, framework
459                // sends non-secure buffer and with out destroying
460                // surfaces, switches to secure buffer thereby exposing
461                // vulnerability on A-family devices. Catch this situation
462                // and handle it gracefully by allowing it to be composed by
463                // GPU.
464                ALOGD_IF(HWC_UTILS_DEBUG, "%s: Handle non-secure video layer"
465                         "during secure playback gracefully", __FUNCTION__);
466                return true;
467            }
468        } else {
469            if (isSecureBuffer(hnd)) {
470                // This code path executes for the following usecase:
471                // For some Apps, when User terminates playback, Framework
472                // doesnt destroy video surface and video surface still
473                // comes to Display HAL. This exposes vulnerability on
474                // A-family. Catch this situation and handle it gracefully
475                // by allowing it to be composed by GPU.
476                ALOGD_IF(HWC_UTILS_DEBUG, "%s: Handle secure video layer"
477                         "during non-secure playback gracefully", __FUNCTION__);
478                return true;
479            }
480        }
481    }
482    return false;
483}
484
485bool isSecureModePolicy(int mdpVersion) {
486    if (mdpVersion < qdutils::MDSS_V5)
487        return true;
488    else
489        return false;
490}
491
492int getBlending(int blending) {
493    switch(blending) {
494    case HWC_BLENDING_NONE:
495        return overlay::utils::OVERLAY_BLENDING_OPAQUE;
496    case HWC_BLENDING_PREMULT:
497        return overlay::utils::OVERLAY_BLENDING_PREMULT;
498    case HWC_BLENDING_COVERAGE :
499    default:
500        return overlay::utils::OVERLAY_BLENDING_COVERAGE;
501    }
502}
503
504//Crops source buffer against destination and FB boundaries
505void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
506                          const hwc_rect_t& scissor, int orient) {
507
508    int& crop_l = crop.left;
509    int& crop_t = crop.top;
510    int& crop_r = crop.right;
511    int& crop_b = crop.bottom;
512    int crop_w = crop.right - crop.left;
513    int crop_h = crop.bottom - crop.top;
514
515    int& dst_l = dst.left;
516    int& dst_t = dst.top;
517    int& dst_r = dst.right;
518    int& dst_b = dst.bottom;
519    int dst_w = abs(dst.right - dst.left);
520    int dst_h = abs(dst.bottom - dst.top);
521
522    const int& sci_l = scissor.left;
523    const int& sci_t = scissor.top;
524    const int& sci_r = scissor.right;
525    const int& sci_b = scissor.bottom;
526    int sci_w = abs(sci_r - sci_l);
527    int sci_h = abs(sci_b - sci_t);
528
529    double leftCutRatio = 0.0, rightCutRatio = 0.0, topCutRatio = 0.0,
530            bottomCutRatio = 0.0;
531
532    if(dst_l < sci_l) {
533        leftCutRatio = (double)(sci_l - dst_l) / (double)dst_w;
534        dst_l = sci_l;
535    }
536
537    if(dst_r > sci_r) {
538        rightCutRatio = (double)(dst_r - sci_r) / (double)dst_w;
539        dst_r = sci_r;
540    }
541
542    if(dst_t < sci_t) {
543        topCutRatio = (double)(sci_t - dst_t) / (double)dst_h;
544        dst_t = sci_t;
545    }
546
547    if(dst_b > sci_b) {
548        bottomCutRatio = (double)(dst_b - sci_b) / (double)dst_h;
549        dst_b = sci_b;
550    }
551
552    calc_cut(leftCutRatio, topCutRatio, rightCutRatio, bottomCutRatio, orient);
553    crop_l += crop_w * leftCutRatio;
554    crop_t += crop_h * topCutRatio;
555    crop_r -= crop_w * rightCutRatio;
556    crop_b -= crop_h * bottomCutRatio;
557}
558
559void getNonWormholeRegion(hwc_display_contents_1_t* list,
560                              hwc_rect_t& nwr)
561{
562    uint32_t last = list->numHwLayers - 1;
563    hwc_rect_t fbDisplayFrame = list->hwLayers[last].displayFrame;
564    //Initiliaze nwr to first frame
565    nwr.left =  list->hwLayers[0].displayFrame.left;
566    nwr.top =  list->hwLayers[0].displayFrame.top;
567    nwr.right =  list->hwLayers[0].displayFrame.right;
568    nwr.bottom =  list->hwLayers[0].displayFrame.bottom;
569
570    for (uint32_t i = 1; i < last; i++) {
571        hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
572        nwr.left   = min(nwr.left, displayFrame.left);
573        nwr.top    = min(nwr.top, displayFrame.top);
574        nwr.right  = max(nwr.right, displayFrame.right);
575        nwr.bottom = max(nwr.bottom, displayFrame.bottom);
576    }
577
578    //Intersect with the framebuffer
579    nwr.left   = max(nwr.left, fbDisplayFrame.left);
580    nwr.top    = max(nwr.top, fbDisplayFrame.top);
581    nwr.right  = min(nwr.right, fbDisplayFrame.right);
582    nwr.bottom = min(nwr.bottom, fbDisplayFrame.bottom);
583
584}
585
586void closeAcquireFds(hwc_display_contents_1_t* list, int dpy) {
587    if(LIKELY(list)) {
588        for(uint32_t i = 0; i < list->numHwLayers; i++) {
589            //Close the acquireFenceFds
590            //HWC_FRAMEBUFFER are -1 already by SF, rest we close.
591            if(list->hwLayers[i].acquireFenceFd >= 0) {
592                close(list->hwLayers[i].acquireFenceFd);
593                list->hwLayers[i].acquireFenceFd = -1;
594            }
595        }
596
597        //Writeback
598        if(dpy > HWC_DISPLAY_EXTERNAL && list->outbufAcquireFenceFd >= 0) {
599            close(list->outbufAcquireFenceFd);
600            list->outbufAcquireFenceFd = -1;
601        }
602    }
603}
604
605int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
606        int fd) {
607    ATRACE_CALL();
608    int ret = 0;
609    int acquireFd[MAX_NUM_APP_LAYERS];
610    int count = 0;
611    int releaseFd = -1;
612    int retireFd = -1;
613    int fbFd = -1;
614    bool swapzero = false;
615    int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
616
617    struct mdp_buf_sync data;
618    memset(&data, 0, sizeof(data));
619    data.acq_fen_fd = acquireFd;
620    data.rel_fen_fd = &releaseFd;
621    data.retire_fen_fd = &retireFd;
622
623    char property[PROPERTY_VALUE_MAX];
624    if(property_get("debug.egl.swapinterval", property, "1") > 0) {
625        if(atoi(property) == 0)
626            swapzero = true;
627    }
628
629    for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
630        int rotFd = ctx->mRotMgr->getRotDevFd();
631        int rotReleaseFd = -1;
632        int rotRetireFd = -1;
633        struct mdp_buf_sync rotData;
634        memset(&rotData, 0, sizeof(rotData));
635        rotData.acq_fen_fd =
636                &ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd;
637        rotData.rel_fen_fd = &rotReleaseFd; //driver to populate this
638        rotData.retire_fen_fd = &rotRetireFd;
639        rotData.session_id = ctx->mLayerRotMap[dpy]->getRot(i)->getSessId();
640        int ret = 0;
641        ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
642        if(ret < 0) {
643            ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed for rot sync, err=%s",
644                    __FUNCTION__, strerror(errno));
645        } else {
646            close(ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd);
647            //For MDP to wait on.
648            ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd =
649                    dup(rotReleaseFd);
650            //A buffer is free to be used by producer as soon as its copied to
651            //rotator
652            ctx->mLayerRotMap[dpy]->getLayer(i)->releaseFenceFd =
653                    rotReleaseFd;
654            //Not used for rotator
655            close(rotRetireFd);
656        }
657    }
658
659    //Accumulate acquireFenceFds for MDP
660    if(dpy > HWC_DISPLAY_EXTERNAL && list->outbufAcquireFenceFd >= 0) {
661        //Writeback output buffer
662        acquireFd[count++] = list->outbufAcquireFenceFd;
663    }
664
665    for(uint32_t i = 0; i < list->numHwLayers; i++) {
666        if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
667                        list->hwLayers[i].acquireFenceFd >= 0) {
668            if(UNLIKELY(swapzero))
669                acquireFd[count++] = -1;
670            else
671                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
672        }
673        if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
674            if(UNLIKELY(swapzero))
675                acquireFd[count++] = -1;
676            else if(fd >= 0) {
677                //set the acquireFD from fd - which is coming from c2d
678                acquireFd[count++] = fd;
679                // Buffer sync IOCTL should be async when using c2d fence is
680                // used
681                data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
682            } else if(list->hwLayers[i].acquireFenceFd >= 0)
683                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
684        }
685    }
686
687    data.acq_fen_fd_cnt = count;
688    fbFd = ctx->dpyAttr[dpy].fd;
689
690    //Waits for acquire fences, returns a release fence
691    if(LIKELY(!swapzero)) {
692        uint64_t start = systemTime();
693        ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
694        ALOGD_IF(HWC_UTILS_DEBUG, "%s: time taken for MSMFB_BUFFER_SYNC IOCTL = %d",
695                            __FUNCTION__, (size_t) ns2ms(systemTime() - start));
696    }
697
698    if(ret < 0) {
699        ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed, err=%s",
700                  __FUNCTION__, strerror(errno));
701        ALOGE("%s: acq_fen_fd_cnt=%d flags=%d fd=%d dpy=%d numHwLayers=%d",
702              __FUNCTION__, data.acq_fen_fd_cnt, data.flags, fbFd,
703              dpy, list->numHwLayers);
704    }
705
706    for(uint32_t i = 0; i < list->numHwLayers; i++) {
707        if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
708           list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
709            //Populate releaseFenceFds.
710            if(UNLIKELY(swapzero)) {
711                list->hwLayers[i].releaseFenceFd = -1;
712            } else if(list->hwLayers[i].releaseFenceFd < 0) {
713                //If rotator has not already populated this field.
714                list->hwLayers[i].releaseFenceFd = dup(releaseFd);
715            }
716        }
717    }
718
719    if(fd >= 0) {
720        close(fd);
721        fd = -1;
722    }
723
724    if (ctx->mCopyBit[dpy])
725        ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
726
727    //Signals when MDP finishes reading rotator buffers.
728    ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
729    close(releaseFd);
730
731    if(UNLIKELY(swapzero))
732        list->retireFenceFd = -1;
733    else
734        list->retireFenceFd = retireFd;
735    return ret;
736}
737
738void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
739        hwc_rect_t& crop, hwc_rect_t& dst) {
740    int hw_w = ctx->dpyAttr[dpy].xres;
741    int hw_h = ctx->dpyAttr[dpy].yres;
742    if(dst.left < 0 || dst.top < 0 ||
743            dst.right > hw_w || dst.bottom > hw_h) {
744        hwc_rect_t scissor = {0, 0, hw_w, hw_h };
745        qhwc::calculate_crop_rects(crop, dst, scissor, transform);
746    }
747}
748
749void setMdpFlags(hwc_layer_1_t *layer,
750        ovutils::eMdpFlags &mdpFlags,
751        int rotDownscale) {
752    private_handle_t *hnd = (private_handle_t *)layer->handle;
753    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
754    const int& transform = layer->transform;
755
756    if(layer->blending == HWC_BLENDING_PREMULT) {
757        ovutils::setMdpFlags(mdpFlags,
758                ovutils::OV_MDP_BLEND_FG_PREMULT);
759    }
760
761    if(isYuvBuffer(hnd)) {
762        if(isSecureBuffer(hnd)) {
763            ovutils::setMdpFlags(mdpFlags,
764                    ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
765        }
766        if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
767                metadata->interlaced) {
768            ovutils::setMdpFlags(mdpFlags,
769                    ovutils::OV_MDP_DEINTERLACE);
770        }
771        //Pre-rotation will be used using rotator.
772        if(transform & HWC_TRANSFORM_ROT_90) {
773            ovutils::setMdpFlags(mdpFlags,
774                    ovutils::OV_MDP_SOURCE_ROTATED_90);
775        }
776    }
777
778    //No 90 component and no rot-downscale then flips done by MDP
779    //If we use rot then it might as well do flips
780    if(!(layer->transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
781        if(layer->transform & HWC_TRANSFORM_FLIP_H) {
782            ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
783        }
784
785        if(layer->transform & HWC_TRANSFORM_FLIP_V) {
786            ovutils::setMdpFlags(mdpFlags,  ovutils::OV_MDP_FLIP_V);
787        }
788    }
789
790    if(metadata &&
791        ((metadata->operation & PP_PARAM_HSIC)
792        || (metadata->operation & PP_PARAM_IGC)
793        || (metadata->operation & PP_PARAM_SHARP2))) {
794        ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_PP_EN);
795    }
796}
797
798int configRotator(Rotator *rot, const Whf& whf,
799        hwc_rect_t& crop, const eMdpFlags& mdpFlags,
800        const eTransform& orient, const int& downscale) {
801    rot->setSource(whf);
802
803    if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
804        qdutils::MDSS_V5) {
805        uint32_t crop_w = (crop.right - crop.left);
806        uint32_t crop_h = (crop.bottom - crop.top);
807        if (ovutils::isYuv(whf.format)) {
808            ovutils::normalizeCrop((uint32_t&)crop.left, crop_w);
809            ovutils::normalizeCrop((uint32_t&)crop.top, crop_h);
810            // For interlaced, crop.h should be 4-aligned
811            if ((mdpFlags & ovutils::OV_MDP_DEINTERLACE) && (crop_h % 4))
812                crop_h = ovutils::aligndown(crop_h, 4);
813            crop.right = crop.left + crop_w;
814            crop.bottom = crop.top + crop_h;
815        }
816        Dim rotCrop(crop.left, crop.top, crop_w, crop_h);
817        rot->setCrop(rotCrop);
818    }
819
820    rot->setFlags(mdpFlags);
821    rot->setTransform(orient);
822    rot->setDownscale(downscale);
823    if(!rot->commit()) return -1;
824    return 0;
825}
826
827int configMdp(Overlay *ov, const PipeArgs& parg,
828        const eTransform& orient, const hwc_rect_t& crop,
829        const hwc_rect_t& pos, const MetaData_t *metadata,
830        const eDest& dest) {
831    ov->setSource(parg, dest);
832    ov->setTransform(orient, dest);
833
834    int crop_w = crop.right - crop.left;
835    int crop_h = crop.bottom - crop.top;
836    Dim dcrop(crop.left, crop.top, crop_w, crop_h);
837    ov->setCrop(dcrop, dest);
838
839    int posW = pos.right - pos.left;
840    int posH = pos.bottom - pos.top;
841    Dim position(pos.left, pos.top, posW, posH);
842    ov->setPosition(position, dest);
843
844    if (metadata)
845        ov->setVisualParams(*metadata, dest);
846
847    if (!ov->commit(dest)) {
848        return -1;
849    }
850    return 0;
851}
852
853void updateSource(eTransform& orient, Whf& whf,
854        hwc_rect_t& crop) {
855    Dim srcCrop(crop.left, crop.top,
856            crop.right - crop.left,
857            crop.bottom - crop.top);
858    orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
859    preRotateSource(orient, whf, srcCrop);
860    if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
861        qdutils::MDSS_V5) {
862        // Source for overlay will be the cropped (and rotated)
863        crop.left = 0;
864        crop.top = 0;
865        crop.right = srcCrop.w;
866        crop.bottom = srcCrop.h;
867        // Set width & height equal to sourceCrop w & h
868        whf.w = srcCrop.w;
869        whf.h = srcCrop.h;
870    } else {
871        crop.left = srcCrop.x;
872        crop.top = srcCrop.y;
873        crop.right = srcCrop.x + srcCrop.w;
874        crop.bottom = srcCrop.y + srcCrop.h;
875    }
876}
877
878int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
879        const int& dpy, eMdpFlags& mdpFlags, const eZorder& z,
880        const eIsFg& isFg, const eDest& dest, Rotator **rot) {
881
882    private_handle_t *hnd = (private_handle_t *)layer->handle;
883    if(!hnd) {
884        ALOGE("%s: layer handle is NULL", __FUNCTION__);
885        ctx->mLayerRotMap[dpy]->reset();
886        return -1;
887    }
888
889    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
890
891    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
892    hwc_rect_t dst = layer->displayFrame;
893    int transform = layer->transform;
894    eTransform orient = static_cast<eTransform>(transform);
895    int downscale = 0;
896    int rotFlags = ovutils::ROT_FLAGS_NONE;
897    Whf whf(getWidth(hnd), getHeight(hnd),
898            getMdpFormat(hnd->format), hnd->size);
899
900    uint32_t x = dst.left, y  = dst.top;
901    uint32_t w = dst.right - dst.left;
902    uint32_t h = dst.bottom - dst.top;
903
904    if(dpy) {
905        // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
906        getActionSafePosition(ctx, dpy, x, y, w, h);
907        // Convert position to hwc_rect_t
908        dst.left = x;
909        dst.top = y;
910        dst.right = w + dst.left;
911        dst.bottom = h + dst.top;
912    }
913
914    if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 &&
915       ctx->mMDP.version < qdutils::MDSS_V5) {
916        downscale =  getDownscaleFactor(
917            crop.right - crop.left,
918            crop.bottom - crop.top,
919            dst.right - dst.left,
920            dst.bottom - dst.top);
921        if(downscale) {
922            rotFlags = ROT_DOWNSCALE_ENABLED;
923        }
924    }
925
926    setMdpFlags(layer, mdpFlags, downscale);
927    trimLayer(ctx, dpy, transform, crop, dst);
928
929    //Will do something only if feature enabled and conditions suitable
930    //hollow call otherwise
931    if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
932        overlay::Writeback *wb = overlay::Writeback::getInstance();
933        whf.format = wb->getOutputFormat();
934    }
935
936    if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
937            ((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
938        *rot = ctx->mRotMgr->getNext();
939        if(*rot == NULL) return -1;
940        BwcPM::setBwc(ctx, crop, dst, transform, mdpFlags);
941        //Configure rotator for pre-rotation
942        if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
943            ALOGE("%s: configRotator failed!", __FUNCTION__);
944            ctx->mOverlay->clear(dpy);
945            return -1;
946        }
947        ctx->mLayerRotMap[dpy]->add(layer, *rot);
948        whf.format = (*rot)->getDstFormat();
949        updateSource(orient, whf, crop);
950        rotFlags |= ovutils::ROT_PREROTATED;
951    }
952
953    //For the mdp, since either we are pre-rotating or MDP does flips
954    orient = OVERLAY_TRANSFORM_0;
955    transform = 0;
956
957    PipeArgs parg(mdpFlags, whf, z, isFg,
958                  static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
959                  (ovutils::eBlending) getBlending(layer->blending));
960
961    if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
962        ALOGE("%s: commit failed for low res panel", __FUNCTION__);
963        ctx->mLayerRotMap[dpy]->reset();
964        return -1;
965    }
966    return 0;
967}
968
969int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
970        const int& dpy, eMdpFlags& mdpFlagsL, const eZorder& z,
971        const eIsFg& isFg, const eDest& lDest, const eDest& rDest,
972        Rotator **rot) {
973    private_handle_t *hnd = (private_handle_t *)layer->handle;
974    if(!hnd) {
975        ALOGE("%s: layer handle is NULL", __FUNCTION__);
976        return -1;
977    }
978
979    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
980
981    int hw_w = ctx->dpyAttr[dpy].xres;
982    int hw_h = ctx->dpyAttr[dpy].yres;
983    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
984    hwc_rect_t dst = layer->displayFrame;
985    int transform = layer->transform;
986    eTransform orient = static_cast<eTransform>(transform);
987    const int downscale = 0;
988    int rotFlags = ROT_FLAGS_NONE;
989
990    Whf whf(getWidth(hnd), getHeight(hnd),
991            getMdpFormat(hnd->format), hnd->size);
992
993    setMdpFlags(layer, mdpFlagsL, 0);
994    trimLayer(ctx, dpy, transform, crop, dst);
995
996    //Will do something only if feature enabled and conditions suitable
997    //hollow call otherwise
998    if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
999        overlay::Writeback *wb = overlay::Writeback::getInstance();
1000        whf.format = wb->getOutputFormat();
1001    }
1002
1003    if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
1004        (*rot) = ctx->mRotMgr->getNext();
1005        if((*rot) == NULL) return -1;
1006        //Configure rotator for pre-rotation
1007        if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
1008            ALOGE("%s: configRotator failed!", __FUNCTION__);
1009            ctx->mOverlay->clear(dpy);
1010            return -1;
1011        }
1012        ctx->mLayerRotMap[dpy]->add(layer, *rot);
1013        whf.format = (*rot)->getDstFormat();
1014        updateSource(orient, whf, crop);
1015        rotFlags |= ROT_PREROTATED;
1016    }
1017
1018    eMdpFlags mdpFlagsR = mdpFlagsL;
1019    setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER);
1020
1021    hwc_rect_t tmp_cropL, tmp_dstL;
1022    hwc_rect_t tmp_cropR, tmp_dstR;
1023
1024    const int lSplit = getLeftSplit(ctx, dpy);
1025
1026    if(lDest != OV_INVALID) {
1027        tmp_cropL = crop;
1028        tmp_dstL = dst;
1029        hwc_rect_t scissor = {0, 0, lSplit, hw_h };
1030        qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
1031    }
1032    if(rDest != OV_INVALID) {
1033        tmp_cropR = crop;
1034        tmp_dstR = dst;
1035        hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
1036        qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
1037    }
1038
1039    //When buffer is H-flipped, contents of mixer config also needs to swapped
1040    //Not needed if the layer is confined to one half of the screen.
1041    //If rotator has been used then it has also done the flips, so ignore them.
1042    if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
1043            && rDest != OV_INVALID && (*rot) == NULL) {
1044        hwc_rect_t new_cropR;
1045        new_cropR.left = tmp_cropL.left;
1046        new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
1047
1048        hwc_rect_t new_cropL;
1049        new_cropL.left  = new_cropR.right;
1050        new_cropL.right = tmp_cropR.right;
1051
1052        tmp_cropL.left =  new_cropL.left;
1053        tmp_cropL.right =  new_cropL.right;
1054
1055        tmp_cropR.left = new_cropR.left;
1056        tmp_cropR.right =  new_cropR.right;
1057
1058    }
1059
1060    //For the mdp, since either we are pre-rotating or MDP does flips
1061    orient = OVERLAY_TRANSFORM_0;
1062    transform = 0;
1063
1064    //configure left mixer
1065    if(lDest != OV_INVALID) {
1066        PipeArgs pargL(mdpFlagsL, whf, z, isFg,
1067                       static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
1068                       (ovutils::eBlending) getBlending(layer->blending));
1069
1070        if(configMdp(ctx->mOverlay, pargL, orient,
1071                tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
1072            ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
1073            return -1;
1074        }
1075    }
1076
1077    //configure right mixer
1078    if(rDest != OV_INVALID) {
1079        PipeArgs pargR(mdpFlagsR, whf, z, isFg,
1080                static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
1081                (ovutils::eBlending) getBlending(layer->blending));
1082
1083        tmp_dstR.right = tmp_dstR.right - lSplit;
1084        tmp_dstR.left = tmp_dstR.left - lSplit;
1085        if(configMdp(ctx->mOverlay, pargR, orient,
1086                tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
1087            ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
1088            return -1;
1089        }
1090    }
1091
1092    return 0;
1093}
1094
1095bool canUseRotator(hwc_context_t *ctx, int dpy) {
1096    if(qdutils::MDPVersion::getInstance().is8x26() &&
1097            isSecondaryConnected(ctx)) {
1098        return false;
1099    }
1100    if(ctx->mMDP.version == qdutils::MDP_V3_0_4)
1101        return false;
1102    return true;
1103}
1104
1105int getLeftSplit(hwc_context_t *ctx, const int& dpy) {
1106    //Default even split for all displays with high res
1107    int lSplit = ctx->dpyAttr[dpy].xres / 2;
1108    if(dpy == HWC_DISPLAY_PRIMARY &&
1109            qdutils::MDPVersion::getInstance().getLeftSplit()) {
1110        //Override if split published by driver for primary
1111        lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
1112    }
1113    return lSplit;
1114}
1115
1116void setupSecondaryObjs(hwc_context_t *ctx, const int& dpy) {
1117    const int rSplit = 0;
1118    ctx->mFBUpdate[dpy] =
1119            IFBUpdate::getObject(ctx->dpyAttr[dpy].xres, rSplit, dpy);
1120    ctx->mMDPComp[dpy] =  MDPComp::getObject(
1121            ctx->dpyAttr[dpy].xres, rSplit, dpy);
1122
1123    int compositionType =
1124            qdutils::QCCompositionType::getInstance().getCompositionType();
1125    if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
1126                           qdutils::COMPOSITION_TYPE_MDP |
1127                           qdutils::COMPOSITION_TYPE_C2D)) {
1128        ctx->mCopyBit[dpy] = new CopyBit();
1129    }
1130
1131    if(ctx->mFBUpdate[dpy])
1132        ctx->mFBUpdate[dpy]->reset();
1133    if(ctx->mMDPComp[dpy])
1134        ctx->mMDPComp[dpy]->reset();
1135    if(ctx->mCopyBit[dpy])
1136        ctx->mCopyBit[dpy]->reset();
1137}
1138
1139void clearSecondaryObjs(hwc_context_t *ctx, const int& dpy) {
1140    if(ctx->mFBUpdate[dpy]) {
1141        delete ctx->mFBUpdate[dpy];
1142        ctx->mFBUpdate[dpy] = NULL;
1143    }
1144    if(ctx->mCopyBit[dpy]){
1145        delete ctx->mCopyBit[dpy];
1146        ctx->mCopyBit[dpy] = NULL;
1147    }
1148    if(ctx->mMDPComp[dpy]) {
1149        delete ctx->mMDPComp[dpy];
1150        ctx->mMDPComp[dpy] = NULL;
1151    }
1152}
1153
1154bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy) {
1155    if(ctx->mMDPComp[dpy]) {
1156        return (ctx->mMDPComp[dpy]->getMDPCompCount() == 0);
1157    }
1158    return true;
1159}
1160
1161void BwcPM::setBwc(hwc_context_t *ctx, const hwc_rect_t& crop,
1162            const hwc_rect_t& dst, const int& transform,
1163            ovutils::eMdpFlags& mdpFlags) {
1164    //Target doesnt support Bwc
1165    if(!qdutils::MDPVersion::getInstance().supportsBWC()) {
1166        return;
1167    }
1168    //src width > MAX mixer supported dim
1169    if((crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
1170        return;
1171    }
1172    //Secondary display connected
1173    if(isSecondaryConnected(ctx)) {
1174        return;
1175    }
1176    //Decimation necessary, cannot use BWC. H/W requirement.
1177    if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
1178        int src_w = crop.right - crop.left;
1179        int src_h = crop.bottom - crop.top;
1180        int dst_w = dst.right - dst.left;
1181        int dst_h = dst.bottom - dst.top;
1182        if(transform & HAL_TRANSFORM_ROT_90) {
1183            swap(src_w, src_h);
1184        }
1185        float horDscale = 0.0f;
1186        float verDscale = 0.0f;
1187        int horzDeci = 0;
1188        int vertDeci = 0;
1189        ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horDscale,
1190                verDscale);
1191        //TODO Use log2f once math.h has it
1192        if((int)horDscale)
1193            horzDeci = (int)(log(horDscale) / log(2));
1194        if((int)verDscale)
1195            vertDeci = (int)(log(verDscale) / log(2));
1196        if(horzDeci || vertDeci) return;
1197    }
1198    //Property
1199    char value[PROPERTY_VALUE_MAX];
1200    property_get("debug.disable.bwc", value, "0");
1201     if(atoi(value)) return;
1202
1203    ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDSS_MDP_BWC_EN);
1204}
1205
1206void LayerRotMap::add(hwc_layer_1_t* layer, Rotator *rot) {
1207    if(mCount >= MAX_SESS) return;
1208    mLayer[mCount] = layer;
1209    mRot[mCount] = rot;
1210    mCount++;
1211}
1212
1213void LayerRotMap::reset() {
1214    for (int i = 0; i < MAX_SESS; i++) {
1215        mLayer[i] = 0;
1216        mRot[i] = 0;
1217    }
1218    mCount = 0;
1219}
1220
1221void LayerRotMap::setReleaseFd(const int& fence) {
1222    for(uint32_t i = 0; i < mCount; i++) {
1223        mRot[i]->setReleaseFd(dup(fence));
1224    }
1225}
1226
1227};//namespace qhwc
1228