hwc_utils.cpp revision b5199b08a351177e2d572b29d04f5a05069b3c2a
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
586bool isSecondaryConfiguring(hwc_context_t* ctx) {
587    return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isConfiguring |
588            ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isConfiguring);
589}
590
591void closeAcquireFds(hwc_display_contents_1_t* list) {
592    if(LIKELY(list)) {
593        for(uint32_t i = 0; i < list->numHwLayers; i++) {
594            //Close the acquireFenceFds
595            //HWC_FRAMEBUFFER are -1 already by SF, rest we close.
596            if(list->hwLayers[i].acquireFenceFd >= 0) {
597                close(list->hwLayers[i].acquireFenceFd);
598                list->hwLayers[i].acquireFenceFd = -1;
599            }
600        }
601    }
602}
603
604int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
605        int fd) {
606    ATRACE_CALL();
607    int ret = 0;
608    int acquireFd[MAX_NUM_APP_LAYERS];
609    int count = 0;
610    int releaseFd = -1;
611    int retireFd = -1;
612    int fbFd = -1;
613    bool swapzero = false;
614    int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
615
616    struct mdp_buf_sync data;
617    memset(&data, 0, sizeof(data));
618    data.acq_fen_fd = acquireFd;
619    data.rel_fen_fd = &releaseFd;
620    data.retire_fen_fd = &retireFd;
621
622    char property[PROPERTY_VALUE_MAX];
623    if(property_get("debug.egl.swapinterval", property, "1") > 0) {
624        if(atoi(property) == 0)
625            swapzero = true;
626    }
627
628    for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
629        int rotFd = ctx->mRotMgr->getRotDevFd();
630        int rotReleaseFd = -1;
631        int rotRetireFd = -1;
632        struct mdp_buf_sync rotData;
633        memset(&rotData, 0, sizeof(rotData));
634        rotData.acq_fen_fd =
635                &ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd;
636        rotData.rel_fen_fd = &rotReleaseFd; //driver to populate this
637        rotData.retire_fen_fd = &rotRetireFd;
638        rotData.session_id = ctx->mLayerRotMap[dpy]->getRot(i)->getSessId();
639        int ret = 0;
640        ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
641        if(ret < 0) {
642            ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed for rot sync, err=%s",
643                    __FUNCTION__, strerror(errno));
644        } else {
645            close(ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd);
646            //For MDP to wait on.
647            ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd =
648                    dup(rotReleaseFd);
649            //A buffer is free to be used by producer as soon as its copied to
650            //rotator
651            ctx->mLayerRotMap[dpy]->getLayer(i)->releaseFenceFd =
652                    rotReleaseFd;
653            //Not used for rotator
654            close(rotRetireFd);
655        }
656    }
657
658    //Accumulate acquireFenceFds for MDP
659    for(uint32_t i = 0; i < list->numHwLayers; i++) {
660        if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
661                        list->hwLayers[i].acquireFenceFd >= 0) {
662            if(UNLIKELY(swapzero))
663                acquireFd[count++] = -1;
664            else
665                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
666        }
667        if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
668            if(UNLIKELY(swapzero))
669                acquireFd[count++] = -1;
670            else if(fd >= 0) {
671                //set the acquireFD from fd - which is coming from c2d
672                acquireFd[count++] = fd;
673                // Buffer sync IOCTL should be async when using c2d fence is
674                // used
675                data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
676            } else if(list->hwLayers[i].acquireFenceFd >= 0)
677                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
678        }
679    }
680
681    data.acq_fen_fd_cnt = count;
682    fbFd = ctx->dpyAttr[dpy].fd;
683
684    //Waits for acquire fences, returns a release fence
685    if(LIKELY(!swapzero)) {
686        uint64_t start = systemTime();
687        ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
688        ALOGD_IF(HWC_UTILS_DEBUG, "%s: time taken for MSMFB_BUFFER_SYNC IOCTL = %d",
689                            __FUNCTION__, (size_t) ns2ms(systemTime() - start));
690    }
691
692    if(ret < 0) {
693        ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed, err=%s",
694                  __FUNCTION__, strerror(errno));
695        ALOGE("%s: acq_fen_fd_cnt=%d flags=%d fd=%d dpy=%d numHwLayers=%d",
696              __FUNCTION__, data.acq_fen_fd_cnt, data.flags, fbFd,
697              dpy, list->numHwLayers);
698    }
699
700    for(uint32_t i = 0; i < list->numHwLayers; i++) {
701        if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
702           list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
703            //Populate releaseFenceFds.
704            if(UNLIKELY(swapzero)) {
705                list->hwLayers[i].releaseFenceFd = -1;
706            } else if(list->hwLayers[i].releaseFenceFd < 0) {
707                //If rotator has not already populated this field.
708                list->hwLayers[i].releaseFenceFd = dup(releaseFd);
709            }
710        }
711    }
712
713    if(fd >= 0) {
714        close(fd);
715        fd = -1;
716    }
717
718    if (ctx->mCopyBit[dpy])
719        ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
720
721    //Signals when MDP finishes reading rotator buffers.
722    ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
723    close(releaseFd);
724
725    if(UNLIKELY(swapzero))
726        list->retireFenceFd = -1;
727    else
728        list->retireFenceFd = retireFd;
729    return ret;
730}
731
732void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
733        hwc_rect_t& crop, hwc_rect_t& dst) {
734    int hw_w = ctx->dpyAttr[dpy].xres;
735    int hw_h = ctx->dpyAttr[dpy].yres;
736    if(dst.left < 0 || dst.top < 0 ||
737            dst.right > hw_w || dst.bottom > hw_h) {
738        hwc_rect_t scissor = {0, 0, hw_w, hw_h };
739        qhwc::calculate_crop_rects(crop, dst, scissor, transform);
740    }
741}
742
743void setMdpFlags(hwc_layer_1_t *layer,
744        ovutils::eMdpFlags &mdpFlags,
745        int rotDownscale) {
746    private_handle_t *hnd = (private_handle_t *)layer->handle;
747    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
748    const int& transform = layer->transform;
749
750    if(layer->blending == HWC_BLENDING_PREMULT) {
751        ovutils::setMdpFlags(mdpFlags,
752                ovutils::OV_MDP_BLEND_FG_PREMULT);
753    }
754
755    if(isYuvBuffer(hnd)) {
756        if(isSecureBuffer(hnd)) {
757            ovutils::setMdpFlags(mdpFlags,
758                    ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
759        }
760        if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
761                metadata->interlaced) {
762            ovutils::setMdpFlags(mdpFlags,
763                    ovutils::OV_MDP_DEINTERLACE);
764        }
765        //Pre-rotation will be used using rotator.
766        if(transform & HWC_TRANSFORM_ROT_90) {
767            ovutils::setMdpFlags(mdpFlags,
768                    ovutils::OV_MDP_SOURCE_ROTATED_90);
769        }
770    }
771
772    //No 90 component and no rot-downscale then flips done by MDP
773    //If we use rot then it might as well do flips
774    if(!(layer->transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
775        if(layer->transform & HWC_TRANSFORM_FLIP_H) {
776            ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
777        }
778
779        if(layer->transform & HWC_TRANSFORM_FLIP_V) {
780            ovutils::setMdpFlags(mdpFlags,  ovutils::OV_MDP_FLIP_V);
781        }
782    }
783
784    if(metadata &&
785        ((metadata->operation & PP_PARAM_HSIC)
786        || (metadata->operation & PP_PARAM_IGC)
787        || (metadata->operation & PP_PARAM_SHARP2))) {
788        ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_PP_EN);
789    }
790}
791
792int configRotator(Rotator *rot, const Whf& whf,
793        hwc_rect_t& crop, const eMdpFlags& mdpFlags,
794        const eTransform& orient, const int& downscale) {
795    rot->setSource(whf);
796
797    if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
798        qdutils::MDSS_V5) {
799        uint32_t crop_w = (crop.right - crop.left);
800        uint32_t crop_h = (crop.bottom - crop.top);
801        if (ovutils::isYuv(whf.format)) {
802            ovutils::normalizeCrop((uint32_t&)crop.left, crop_w);
803            ovutils::normalizeCrop((uint32_t&)crop.top, crop_h);
804            // For interlaced, crop.h should be 4-aligned
805            if ((mdpFlags & ovutils::OV_MDP_DEINTERLACE) && (crop_h % 4))
806                crop_h = ovutils::aligndown(crop_h, 4);
807            crop.right = crop.left + crop_w;
808            crop.bottom = crop.top + crop_h;
809        }
810        Dim rotCrop(crop.left, crop.top, crop_w, crop_h);
811        rot->setCrop(rotCrop);
812    }
813
814    rot->setFlags(mdpFlags);
815    rot->setTransform(orient);
816    rot->setDownscale(downscale);
817    if(!rot->commit()) return -1;
818    return 0;
819}
820
821int configMdp(Overlay *ov, const PipeArgs& parg,
822        const eTransform& orient, const hwc_rect_t& crop,
823        const hwc_rect_t& pos, const MetaData_t *metadata,
824        const eDest& dest) {
825    ov->setSource(parg, dest);
826    ov->setTransform(orient, dest);
827
828    int crop_w = crop.right - crop.left;
829    int crop_h = crop.bottom - crop.top;
830    Dim dcrop(crop.left, crop.top, crop_w, crop_h);
831    ov->setCrop(dcrop, dest);
832
833    int posW = pos.right - pos.left;
834    int posH = pos.bottom - pos.top;
835    Dim position(pos.left, pos.top, posW, posH);
836    ov->setPosition(position, dest);
837
838    if (metadata)
839        ov->setVisualParams(*metadata, dest);
840
841    if (!ov->commit(dest)) {
842        return -1;
843    }
844    return 0;
845}
846
847void updateSource(eTransform& orient, Whf& whf,
848        hwc_rect_t& crop) {
849    Dim srcCrop(crop.left, crop.top,
850            crop.right - crop.left,
851            crop.bottom - crop.top);
852    orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
853    preRotateSource(orient, whf, srcCrop);
854    if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
855        qdutils::MDSS_V5) {
856        // Source for overlay will be the cropped (and rotated)
857        crop.left = 0;
858        crop.top = 0;
859        crop.right = srcCrop.w;
860        crop.bottom = srcCrop.h;
861        // Set width & height equal to sourceCrop w & h
862        whf.w = srcCrop.w;
863        whf.h = srcCrop.h;
864    } else {
865        crop.left = srcCrop.x;
866        crop.top = srcCrop.y;
867        crop.right = srcCrop.x + srcCrop.w;
868        crop.bottom = srcCrop.y + srcCrop.h;
869    }
870}
871
872int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
873        const int& dpy, eMdpFlags& mdpFlags, const eZorder& z,
874        const eIsFg& isFg, const eDest& dest, Rotator **rot) {
875
876    private_handle_t *hnd = (private_handle_t *)layer->handle;
877    if(!hnd) {
878        ALOGE("%s: layer handle is NULL", __FUNCTION__);
879        ctx->mLayerRotMap[dpy]->reset();
880        return -1;
881    }
882
883    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
884
885    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
886    hwc_rect_t dst = layer->displayFrame;
887    int transform = layer->transform;
888    eTransform orient = static_cast<eTransform>(transform);
889    int downscale = 0;
890    int rotFlags = ovutils::ROT_FLAGS_NONE;
891    Whf whf(getWidth(hnd), getHeight(hnd),
892            getMdpFormat(hnd->format), hnd->size);
893
894    uint32_t x = dst.left, y  = dst.top;
895    uint32_t w = dst.right - dst.left;
896    uint32_t h = dst.bottom - dst.top;
897
898    if(dpy) {
899        // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
900        getActionSafePosition(ctx, dpy, x, y, w, h);
901        // Convert position to hwc_rect_t
902        dst.left = x;
903        dst.top = y;
904        dst.right = w + dst.left;
905        dst.bottom = h + dst.top;
906    }
907
908    if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 &&
909       ctx->mMDP.version < qdutils::MDSS_V5) {
910        downscale =  getDownscaleFactor(
911            crop.right - crop.left,
912            crop.bottom - crop.top,
913            dst.right - dst.left,
914            dst.bottom - dst.top);
915        if(downscale) {
916            rotFlags = ROT_DOWNSCALE_ENABLED;
917        }
918    }
919
920    setMdpFlags(layer, mdpFlags, downscale);
921    trimLayer(ctx, dpy, transform, crop, dst);
922
923    //Will do something only if feature enabled and conditions suitable
924    //hollow call otherwise
925    if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
926        overlay::Writeback *wb = overlay::Writeback::getInstance();
927        whf.format = wb->getOutputFormat();
928    }
929
930    if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
931            ((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
932        *rot = ctx->mRotMgr->getNext();
933        if(*rot == NULL) return -1;
934        BwcPM::setBwc(ctx, crop, dst, transform, mdpFlags);
935        //Configure rotator for pre-rotation
936        if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
937            ALOGE("%s: configRotator failed!", __FUNCTION__);
938            ctx->mOverlay->clear(dpy);
939            return -1;
940        }
941        ctx->mLayerRotMap[dpy]->add(layer, *rot);
942        whf.format = (*rot)->getDstFormat();
943        updateSource(orient, whf, crop);
944        rotFlags |= ovutils::ROT_PREROTATED;
945    }
946
947    //For the mdp, since either we are pre-rotating or MDP does flips
948    orient = OVERLAY_TRANSFORM_0;
949    transform = 0;
950
951    PipeArgs parg(mdpFlags, whf, z, isFg,
952                  static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
953                  (ovutils::eBlending) getBlending(layer->blending));
954
955    if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
956        ALOGE("%s: commit failed for low res panel", __FUNCTION__);
957        ctx->mLayerRotMap[dpy]->reset();
958        return -1;
959    }
960    return 0;
961}
962
963int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
964        const int& dpy, eMdpFlags& mdpFlagsL, const eZorder& z,
965        const eIsFg& isFg, const eDest& lDest, const eDest& rDest,
966        Rotator **rot) {
967    private_handle_t *hnd = (private_handle_t *)layer->handle;
968    if(!hnd) {
969        ALOGE("%s: layer handle is NULL", __FUNCTION__);
970        return -1;
971    }
972
973    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
974
975    int hw_w = ctx->dpyAttr[dpy].xres;
976    int hw_h = ctx->dpyAttr[dpy].yres;
977    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
978    hwc_rect_t dst = layer->displayFrame;
979    int transform = layer->transform;
980    eTransform orient = static_cast<eTransform>(transform);
981    const int downscale = 0;
982    int rotFlags = ROT_FLAGS_NONE;
983
984    Whf whf(getWidth(hnd), getHeight(hnd),
985            getMdpFormat(hnd->format), hnd->size);
986
987    setMdpFlags(layer, mdpFlagsL, 0);
988    trimLayer(ctx, dpy, transform, crop, dst);
989
990    //Will do something only if feature enabled and conditions suitable
991    //hollow call otherwise
992    if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
993        overlay::Writeback *wb = overlay::Writeback::getInstance();
994        whf.format = wb->getOutputFormat();
995    }
996
997    if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
998        (*rot) = ctx->mRotMgr->getNext();
999        if((*rot) == NULL) return -1;
1000        //Configure rotator for pre-rotation
1001        if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
1002            ALOGE("%s: configRotator failed!", __FUNCTION__);
1003            ctx->mOverlay->clear(dpy);
1004            return -1;
1005        }
1006        ctx->mLayerRotMap[dpy]->add(layer, *rot);
1007        whf.format = (*rot)->getDstFormat();
1008        updateSource(orient, whf, crop);
1009        rotFlags |= ROT_PREROTATED;
1010    }
1011
1012    eMdpFlags mdpFlagsR = mdpFlagsL;
1013    setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER);
1014
1015    hwc_rect_t tmp_cropL, tmp_dstL;
1016    hwc_rect_t tmp_cropR, tmp_dstR;
1017
1018    const int lSplit = getLeftSplit(ctx, dpy);
1019
1020    if(lDest != OV_INVALID) {
1021        tmp_cropL = crop;
1022        tmp_dstL = dst;
1023        hwc_rect_t scissor = {0, 0, lSplit, hw_h };
1024        qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
1025    }
1026    if(rDest != OV_INVALID) {
1027        tmp_cropR = crop;
1028        tmp_dstR = dst;
1029        hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
1030        qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
1031    }
1032
1033    //When buffer is H-flipped, contents of mixer config also needs to swapped
1034    //Not needed if the layer is confined to one half of the screen.
1035    //If rotator has been used then it has also done the flips, so ignore them.
1036    if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
1037            && rDest != OV_INVALID && (*rot) == NULL) {
1038        hwc_rect_t new_cropR;
1039        new_cropR.left = tmp_cropL.left;
1040        new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
1041
1042        hwc_rect_t new_cropL;
1043        new_cropL.left  = new_cropR.right;
1044        new_cropL.right = tmp_cropR.right;
1045
1046        tmp_cropL.left =  new_cropL.left;
1047        tmp_cropL.right =  new_cropL.right;
1048
1049        tmp_cropR.left = new_cropR.left;
1050        tmp_cropR.right =  new_cropR.right;
1051
1052    }
1053
1054    //For the mdp, since either we are pre-rotating or MDP does flips
1055    orient = OVERLAY_TRANSFORM_0;
1056    transform = 0;
1057
1058    //configure left mixer
1059    if(lDest != OV_INVALID) {
1060        PipeArgs pargL(mdpFlagsL, whf, z, isFg,
1061                       static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
1062                       (ovutils::eBlending) getBlending(layer->blending));
1063
1064        if(configMdp(ctx->mOverlay, pargL, orient,
1065                tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
1066            ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
1067            return -1;
1068        }
1069    }
1070
1071    //configure right mixer
1072    if(rDest != OV_INVALID) {
1073        PipeArgs pargR(mdpFlagsR, whf, z, isFg,
1074                static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
1075                (ovutils::eBlending) getBlending(layer->blending));
1076
1077        tmp_dstR.right = tmp_dstR.right - lSplit;
1078        tmp_dstR.left = tmp_dstR.left - lSplit;
1079        if(configMdp(ctx->mOverlay, pargR, orient,
1080                tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
1081            ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
1082            return -1;
1083        }
1084    }
1085
1086    return 0;
1087}
1088
1089bool canUseRotator(hwc_context_t *ctx, int dpy) {
1090    if(qdutils::MDPVersion::getInstance().is8x26() &&
1091            ctx->mExtDisplay->isExternalConnected()) {
1092        return false;
1093    }
1094    if(ctx->mMDP.version == qdutils::MDP_V3_0_4)
1095        return false;
1096    return true;
1097}
1098
1099int getLeftSplit(hwc_context_t *ctx, const int& dpy) {
1100    //Default even split for all displays with high res
1101    int lSplit = ctx->dpyAttr[dpy].xres / 2;
1102    if(dpy == HWC_DISPLAY_PRIMARY &&
1103            qdutils::MDPVersion::getInstance().getLeftSplit()) {
1104        //Override if split published by driver for primary
1105        lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
1106    }
1107    return lSplit;
1108}
1109
1110void setupSecondaryObjs(hwc_context_t *ctx, const int& dpy) {
1111    const int rSplit = 0;
1112    ctx->mFBUpdate[dpy] =
1113            IFBUpdate::getObject(ctx->dpyAttr[dpy].xres, rSplit, dpy);
1114    ctx->mMDPComp[dpy] =  MDPComp::getObject(
1115            ctx->dpyAttr[dpy].xres, rSplit, dpy);
1116
1117    int compositionType =
1118            qdutils::QCCompositionType::getInstance().getCompositionType();
1119    if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
1120                           qdutils::COMPOSITION_TYPE_MDP |
1121                           qdutils::COMPOSITION_TYPE_C2D)) {
1122        ctx->mCopyBit[dpy] = new CopyBit();
1123    }
1124}
1125
1126void clearSecondaryObjs(hwc_context_t *ctx, const int& dpy) {
1127    if(ctx->mFBUpdate[dpy]) {
1128        delete ctx->mFBUpdate[dpy];
1129        ctx->mFBUpdate[dpy] = NULL;
1130    }
1131    if(ctx->mCopyBit[dpy]){
1132        delete ctx->mCopyBit[dpy];
1133        ctx->mCopyBit[dpy] = NULL;
1134    }
1135    if(ctx->mMDPComp[dpy]) {
1136        delete ctx->mMDPComp[dpy];
1137        ctx->mMDPComp[dpy] = NULL;
1138    }
1139}
1140
1141void BwcPM::setBwc(hwc_context_t *ctx, const hwc_rect_t& crop,
1142            const hwc_rect_t& dst, const int& transform,
1143            ovutils::eMdpFlags& mdpFlags) {
1144    //Target doesnt support Bwc
1145    if(!qdutils::MDPVersion::getInstance().supportsBWC()) {
1146        return;
1147    }
1148    //src width > MAX mixer supported dim
1149    if((crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
1150        return;
1151    }
1152    //External connected
1153    if(ctx->mExtDisplay->isExternalConnected()) {
1154        return;
1155    }
1156    //Decimation necessary, cannot use BWC. H/W requirement.
1157    if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
1158        int src_w = crop.right - crop.left;
1159        int src_h = crop.bottom - crop.top;
1160        int dst_w = dst.right - dst.left;
1161        int dst_h = dst.bottom - dst.top;
1162        if(transform & HAL_TRANSFORM_ROT_90) {
1163            swap(src_w, src_h);
1164        }
1165        float horDscale = 0.0f;
1166        float verDscale = 0.0f;
1167        int horzDeci = 0;
1168        int vertDeci = 0;
1169        ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horDscale,
1170                verDscale);
1171        //TODO Use log2f once math.h has it
1172        if((int)horDscale)
1173            horzDeci = (int)(log(horDscale) / log(2));
1174        if((int)verDscale)
1175            vertDeci = (int)(log(verDscale) / log(2));
1176        if(horzDeci || vertDeci) return;
1177    }
1178    //Property
1179    char value[PROPERTY_VALUE_MAX];
1180    property_get("debug.disable.bwc", value, "0");
1181     if(atoi(value)) return;
1182
1183    ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDSS_MDP_BWC_EN);
1184}
1185
1186void LayerRotMap::add(hwc_layer_1_t* layer, Rotator *rot) {
1187    if(mCount >= MAX_SESS) return;
1188    mLayer[mCount] = layer;
1189    mRot[mCount] = rot;
1190    mCount++;
1191}
1192
1193void LayerRotMap::reset() {
1194    for (int i = 0; i < MAX_SESS; i++) {
1195        mLayer[i] = 0;
1196        mRot[i] = 0;
1197    }
1198    mCount = 0;
1199}
1200
1201void LayerRotMap::setReleaseFd(const int& fence) {
1202    for(uint32_t i = 0; i < mCount; i++) {
1203        mRot[i]->setReleaseFd(dup(fence));
1204    }
1205}
1206
1207};//namespace qhwc
1208