Home | History | Annotate | Download | only in libhwcomposer
      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 
     43 using namespace qClient;
     44 using namespace qService;
     45 using namespace android;
     46 using namespace overlay;
     47 using namespace overlay::utils;
     48 namespace ovutils = overlay::utils;
     49 
     50 namespace qhwc {
     51 
     52 static 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 
    125 void 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 
    189 void 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 
    240 void 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 */
    249 void 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 
    303 bool 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 
    322 bool 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 
    330 bool 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
    346 static 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 
    363 void 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 
    427 static 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 
    445 bool 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 
    485 bool isSecureModePolicy(int mdpVersion) {
    486     if (mdpVersion < qdutils::MDSS_V5)
    487         return true;
    488     else
    489         return false;
    490 }
    491 
    492 int 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
    505 void 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 
    559 void 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 
    586 void 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 
    605 int 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 
    738 void 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 
    749 void 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 
    798 int 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 
    827 int 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 
    853 void 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 
    878 int 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 
    969 int 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 
   1095 bool 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 
   1105 int 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 
   1116 void 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 
   1139 void 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 
   1154 bool 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 
   1161 void 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 
   1206 void 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 
   1213 void 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 
   1221 void 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