Home | History | Annotate | Download | only in libhwcomposer
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  * Copyright (C) 2012-2014, 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 <linux/fb.h>
     25 #include <binder/IServiceManager.h>
     26 #include <EGL/egl.h>
     27 #include <cutils/properties.h>
     28 #include <utils/Trace.h>
     29 #include <gralloc_priv.h>
     30 #include <overlay.h>
     31 #include <overlayRotator.h>
     32 #include <overlayWriteback.h>
     33 #include "hwc_utils.h"
     34 #include "hwc_mdpcomp.h"
     35 #include "hwc_fbupdate.h"
     36 #include "hwc_ad.h"
     37 #include "mdp_version.h"
     38 #include "hwc_copybit.h"
     39 #include "hwc_dump_layers.h"
     40 #include "hdmi.h"
     41 #include "hwc_qclient.h"
     42 #include "QService.h"
     43 #include "comptype.h"
     44 #include "hwc_virtual.h"
     45 #include "qd_utils.h"
     46 #include <sys/sysinfo.h>
     47 
     48 using namespace qClient;
     49 using namespace qService;
     50 using namespace android;
     51 using namespace overlay;
     52 using namespace overlay::utils;
     53 namespace ovutils = overlay::utils;
     54 
     55 #ifdef QCOM_BSP
     56 #ifdef __cplusplus
     57 extern "C" {
     58 #endif
     59 
     60 EGLAPI EGLBoolean eglGpuPerfHintQCOM(EGLDisplay dpy, EGLContext ctx,
     61                                            EGLint *attrib_list);
     62 #define EGL_GPU_HINT_1        0x32D0
     63 #define EGL_GPU_HINT_2        0x32D1
     64 
     65 #define EGL_GPU_LEVEL_0       0x0
     66 #define EGL_GPU_LEVEL_1       0x1
     67 #define EGL_GPU_LEVEL_2       0x2
     68 #define EGL_GPU_LEVEL_3       0x3
     69 #define EGL_GPU_LEVEL_4       0x4
     70 #define EGL_GPU_LEVEL_5       0x5
     71 
     72 #ifdef __cplusplus
     73 }
     74 #endif
     75 #endif
     76 
     77 #define PROP_DEFAULT_APPBUFFER  "ro.sf.default_app_buffer"
     78 #define MAX_RAM_SIZE  512*1024*1024
     79 #define qHD_WIDTH 540
     80 
     81 
     82 namespace qhwc {
     83 
     84 // Std refresh rates for digital videos- 24p, 30p, 48p and 60p
     85 uint32_t stdRefreshRates[] = { 30, 24, 48, 60 };
     86 
     87 bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
     88 {
     89     return !((xres > qdutils::MDPVersion::getInstance().getMaxPipeWidth() &&
     90                 !isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY)) ||
     91             (xres < MIN_DISPLAY_XRES || yres < MIN_DISPLAY_YRES));
     92 }
     93 
     94 void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig,
     95                       int width, int height) {
     96     //Store original display resolution.
     97     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_orig;
     98     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_orig;
     99     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = false;
    100     char property[PROPERTY_VALUE_MAX] = {'\0'};
    101     char *yptr = NULL;
    102     if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
    103         yptr = strcasestr(property,"x");
    104         if(yptr) {
    105             int xres_new = atoi(property);
    106             int yres_new = atoi(yptr + 1);
    107             if (isValidResolution(ctx,xres_new,yres_new) &&
    108                 xres_new != xres_orig && yres_new != yres_orig) {
    109                 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_new;
    110                 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_new;
    111                 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = true;
    112 
    113                 //Caluculate DPI according to changed resolution.
    114                 float xdpi = ((float)xres_new * 25.4f) / (float)width;
    115                 float ydpi = ((float)yres_new * 25.4f) / (float)height;
    116                 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
    117                 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
    118             }
    119         }
    120     }
    121 }
    122 
    123 // Initialize hdmi display attributes based on
    124 // hdmi display class state
    125 void updateDisplayInfo(hwc_context_t* ctx, int dpy) {
    126     ctx->dpyAttr[dpy].fd = ctx->mHDMIDisplay->getFd();
    127     ctx->dpyAttr[dpy].xres = ctx->mHDMIDisplay->getWidth();
    128     ctx->dpyAttr[dpy].yres = ctx->mHDMIDisplay->getHeight();
    129     ctx->dpyAttr[dpy].mMDPScalingMode = ctx->mHDMIDisplay->getMDPScalingMode();
    130     ctx->dpyAttr[dpy].vsync_period = ctx->mHDMIDisplay->getVsyncPeriod();
    131     //FIXME: for now assume HDMI as secure
    132     //Will need to read the HDCP status from the driver
    133     //and update this accordingly
    134     ctx->dpyAttr[dpy].secure = true;
    135     ctx->mViewFrame[dpy].left = 0;
    136     ctx->mViewFrame[dpy].top = 0;
    137     ctx->mViewFrame[dpy].right = ctx->dpyAttr[dpy].xres;
    138     ctx->mViewFrame[dpy].bottom = ctx->dpyAttr[dpy].yres;
    139 }
    140 
    141 // Reset hdmi display attributes and list stats structures
    142 void resetDisplayInfo(hwc_context_t* ctx, int dpy) {
    143     memset(&(ctx->dpyAttr[dpy]), 0, sizeof(ctx->dpyAttr[dpy]));
    144     memset(&(ctx->listStats[dpy]), 0, sizeof(ctx->listStats[dpy]));
    145     // We reset the fd to -1 here but External display class is responsible
    146     // for it when the display is disconnected. This is handled as part of
    147     // EXTERNAL_OFFLINE event.
    148     ctx->dpyAttr[dpy].fd = -1;
    149 }
    150 
    151 // Initialize composition resources
    152 void initCompositionResources(hwc_context_t* ctx, int dpy) {
    153     ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy);
    154     ctx->mMDPComp[dpy] = MDPComp::getObject(ctx, dpy);
    155 }
    156 
    157 void destroyCompositionResources(hwc_context_t* ctx, int dpy) {
    158     if(ctx->mFBUpdate[dpy]) {
    159         delete ctx->mFBUpdate[dpy];
    160         ctx->mFBUpdate[dpy] = NULL;
    161     }
    162     if(ctx->mMDPComp[dpy]) {
    163         delete ctx->mMDPComp[dpy];
    164         ctx->mMDPComp[dpy] = NULL;
    165     }
    166 }
    167 
    168 static int openFramebufferDevice(hwc_context_t *ctx)
    169 {
    170     struct fb_fix_screeninfo finfo;
    171     struct fb_var_screeninfo info;
    172 
    173     int fb_fd = openFb(HWC_DISPLAY_PRIMARY);
    174     if(fb_fd < 0) {
    175         ALOGE("%s: Error Opening FB : %s", __FUNCTION__, strerror(errno));
    176         return -errno;
    177     }
    178 
    179     if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &info) == -1) {
    180         ALOGE("%s:Error in ioctl FBIOGET_VSCREENINFO: %s", __FUNCTION__,
    181                                                        strerror(errno));
    182         close(fb_fd);
    183         return -errno;
    184     }
    185 
    186     if (int(info.width) <= 0 || int(info.height) <= 0) {
    187         // the driver doesn't return that information
    188         // default to 160 dpi
    189         info.width  = (int)(((float)info.xres * 25.4f)/160.0f + 0.5f);
    190         info.height = (int)(((float)info.yres * 25.4f)/160.0f + 0.5f);
    191     }
    192 
    193     float xdpi = ((float)info.xres * 25.4f) / (float)info.width;
    194     float ydpi = ((float)info.yres * 25.4f) / (float)info.height;
    195 
    196 #ifdef MSMFB_METADATA_GET
    197     struct msmfb_metadata metadata;
    198     memset(&metadata, 0 , sizeof(metadata));
    199     metadata.op = metadata_op_frame_rate;
    200 
    201     if (ioctl(fb_fd, MSMFB_METADATA_GET, &metadata) == -1) {
    202         ALOGE("%s:Error retrieving panel frame rate: %s", __FUNCTION__,
    203                                                       strerror(errno));
    204         close(fb_fd);
    205         return -errno;
    206     }
    207 
    208     float fps  = (float)metadata.data.panel_frame_rate;
    209 #else
    210     //XXX: Remove reserved field usage on all baselines
    211     //The reserved[3] field is used to store FPS by the driver.
    212     float fps  = info.reserved[3] & 0xFF;
    213 #endif
    214 
    215     if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
    216         ALOGE("%s:Error in ioctl FBIOGET_FSCREENINFO: %s", __FUNCTION__,
    217                                                        strerror(errno));
    218         close(fb_fd);
    219         return -errno;
    220     }
    221 
    222     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = fb_fd;
    223     //xres, yres may not be 32 aligned
    224     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].stride = finfo.line_length /(info.xres/8);
    225     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = info.xres;
    226     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres;
    227     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
    228     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
    229     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].refreshRate = (uint32_t)fps;
    230     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].dynRefreshRate = (uint32_t)fps;
    231     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].secure = true;
    232     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
    233             (uint32_t)(1000000000l / fps);
    234 
    235     //To change resolution of primary display
    236     changeResolution(ctx, info.xres, info.yres, info.width, info.height);
    237 
    238     //Unblank primary on first boot
    239     if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
    240         ALOGE("%s: Failed to unblank display", __FUNCTION__);
    241         return -errno;
    242     }
    243     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive = true;
    244 
    245     return 0;
    246 }
    247 
    248 static void changeDefaultAppBufferCount() {
    249     struct sysinfo info;
    250     unsigned long int ramSize = 0;
    251     if (!sysinfo(&info)) {
    252            ramSize = info.totalram ;
    253     }
    254     int fb_fd = -1;
    255     struct fb_var_screeninfo sInfo ={0};
    256     fb_fd = open("/dev/graphics/fb0", O_RDONLY);
    257     if (fb_fd >=0) {
    258         ioctl(fb_fd, FBIOGET_VSCREENINFO, &sInfo);
    259         close(fb_fd);
    260     }
    261     if ((ramSize && ramSize < MAX_RAM_SIZE) &&
    262          (sInfo.xres &&  sInfo.xres <= qHD_WIDTH )) {
    263                   property_set(PROP_DEFAULT_APPBUFFER, "2");
    264     }
    265 }
    266 
    267 void initContext(hwc_context_t *ctx)
    268 {
    269     overlay::Overlay::initOverlay();
    270     ctx->mHDMIDisplay = new HDMIDisplay();
    271     uint32_t priW = 0, priH = 0;
    272     // 1. HDMI as Primary
    273     //    -If HDMI cable is connected, read display configs from edid data
    274     //    -If HDMI cable is not connected then use default data in vscreeninfo
    275     // 2. HDMI as External
    276     //    -Initialize HDMI class for use with external display
    277     //    -Use vscreeninfo to populate display configs
    278     if(ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
    279         int connected = ctx->mHDMIDisplay->getConnectedState();
    280         if(connected == 1) {
    281             ctx->mHDMIDisplay->configure();
    282             updateDisplayInfo(ctx, HWC_DISPLAY_PRIMARY);
    283             ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
    284         } else {
    285             openFramebufferDevice(ctx);
    286             ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = false;
    287         }
    288     } else {
    289         openFramebufferDevice(ctx);
    290         ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
    291         // Send the primary resolution to the hdmi display class
    292         // to be used for MDP scaling functionality
    293         priW = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
    294         priH = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
    295         ctx->mHDMIDisplay->setPrimaryAttributes(priW, priH);
    296     }
    297 
    298     char value[PROPERTY_VALUE_MAX];
    299     ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
    300     ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
    301     ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
    302     ctx->mOverlay = overlay::Overlay::getInstance();
    303     ctx->mRotMgr = RotMgr::getInstance();
    304     ctx->mBWCEnabled = qdutils::MDPVersion::getInstance().supportsBWC();
    305 
    306     //default_app_buffer for ferrum
    307     if (ctx->mMDP.version ==  qdutils::MDP_V3_0_5) {
    308        changeDefaultAppBufferCount();
    309     }
    310     // Initialize composition objects for the primary display
    311     initCompositionResources(ctx, HWC_DISPLAY_PRIMARY);
    312 
    313     // Check if the target supports copybit compostion (dyn/mdp) to
    314     // decide if we need to open the copybit module.
    315     int compositionType =
    316         qdutils::QCCompositionType::getInstance().getCompositionType();
    317 
    318     // Only MDP copybit is used
    319     if ((compositionType & (qdutils::COMPOSITION_TYPE_DYN |
    320             qdutils::COMPOSITION_TYPE_MDP)) &&
    321             ((qdutils::MDPVersion::getInstance().getMDPVersion() ==
    322             qdutils::MDP_V3_0_4) ||
    323             (qdutils::MDPVersion::getInstance().getMDPVersion() ==
    324             qdutils::MDP_V3_0_5))) {
    325         ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
    326                                                          HWC_DISPLAY_PRIMARY);
    327     }
    328 
    329     ctx->mHWCVirtual = new HWCVirtualVDS();
    330     ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive = false;
    331     ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = false;
    332     ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false;
    333     ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false;
    334     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].mMDPScalingMode= false;
    335     ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode = false;
    336     ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].mMDPScalingMode = false;
    337 
    338     //Initialize the primary display viewFrame info
    339     ctx->mViewFrame[HWC_DISPLAY_PRIMARY].left = 0;
    340     ctx->mViewFrame[HWC_DISPLAY_PRIMARY].top = 0;
    341     ctx->mViewFrame[HWC_DISPLAY_PRIMARY].right =
    342         (int)ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
    343     ctx->mViewFrame[HWC_DISPLAY_PRIMARY].bottom =
    344          (int)ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
    345 
    346     for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
    347         ctx->mHwcDebug[i] = new HwcDebug(i);
    348         ctx->mLayerRotMap[i] = new LayerRotMap();
    349         ctx->mAnimationState[i] = ANIMATION_STOPPED;
    350         ctx->dpyAttr[i].mActionSafePresent = false;
    351         ctx->dpyAttr[i].mAsWidthRatio = 0;
    352         ctx->dpyAttr[i].mAsHeightRatio = 0;
    353     }
    354 
    355     for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
    356         ctx->mPrevHwLayerCount[i] = 0;
    357     }
    358 
    359     MDPComp::init(ctx);
    360     ctx->mAD = new AssertiveDisplay(ctx);
    361 
    362     ctx->vstate.enable = false;
    363     ctx->vstate.fakevsync = false;
    364     ctx->mExtOrientation = 0;
    365     ctx->numActiveDisplays = 1;
    366 
    367     //Right now hwc starts the service but anybody could do it, or it could be
    368     //independent process as well.
    369     QService::init();
    370     sp<IQClient> client = new QClient(ctx);
    371     android::sp<qService::IQService> qservice_sp = interface_cast<IQService>(
    372             defaultServiceManager()->getService(
    373             String16("display.qservice")));
    374     if (qservice_sp.get()) {
    375       qservice_sp->connect(client);
    376     } else {
    377       ALOGE("%s: Failed to acquire service pointer", __FUNCTION__);
    378       return ;
    379     }
    380 
    381     // Initialize device orientation to its default orientation
    382     ctx->deviceOrientation = 0;
    383     ctx->mBufferMirrorMode = false;
    384 
    385     property_get("sys.hwc.windowbox_aspect_ratio_tolerance", value, "0");
    386     ctx->mAspectRatioToleranceLevel = (((float)atoi(value)) / 100.0f);
    387 
    388     ctx->enableABC = false;
    389     property_get("debug.sf.hwc.canUseABC", value, "0");
    390     ctx->enableABC  = atoi(value) ? true : false;
    391 
    392     // Initialize gpu perfomance hint related parameters
    393     property_get("sys.hwc.gpu_perf_mode", value, "0");
    394 #ifdef QCOM_BSP
    395     ctx->mGPUHintInfo.mGpuPerfModeEnable = atoi(value)? true : false;
    396 
    397     ctx->mGPUHintInfo.mEGLDisplay = NULL;
    398     ctx->mGPUHintInfo.mEGLContext = NULL;
    399     ctx->mGPUHintInfo.mCompositionState = COMPOSITION_STATE_MDP;
    400     ctx->mGPUHintInfo.mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
    401 #endif
    402     // Read the system property to determine if windowboxing feature is enabled.
    403     ctx->mWindowboxFeature = false;
    404     if(property_get("sys.hwc.windowbox_feature", value, "false")
    405             && !strcmp(value, "true")) {
    406         ctx->mWindowboxFeature = true;
    407     }
    408 
    409     ctx->mUseMetaDataRefreshRate = true;
    410     if(property_get("persist.metadata_dynfps.disable", value, "false")
    411             && !strcmp(value, "true")) {
    412         ctx->mUseMetaDataRefreshRate = false;
    413     }
    414 
    415     memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
    416     ctx->mHPDEnabled = false;
    417     ALOGI("Initializing Qualcomm Hardware Composer");
    418     ALOGI("MDP version: %d", ctx->mMDP.version);
    419 }
    420 
    421 void closeContext(hwc_context_t *ctx)
    422 {
    423     if(ctx->mOverlay) {
    424         delete ctx->mOverlay;
    425         ctx->mOverlay = NULL;
    426     }
    427 
    428     if(ctx->mRotMgr) {
    429         delete ctx->mRotMgr;
    430         ctx->mRotMgr = NULL;
    431     }
    432 
    433     for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
    434         if(ctx->mCopyBit[i]) {
    435             delete ctx->mCopyBit[i];
    436             ctx->mCopyBit[i] = NULL;
    437         }
    438     }
    439 
    440     if(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd) {
    441         close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd);
    442         ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1;
    443     }
    444 
    445     if(ctx->mHDMIDisplay) {
    446         delete ctx->mHDMIDisplay;
    447         ctx->mHDMIDisplay = NULL;
    448     }
    449 
    450     for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
    451         destroyCompositionResources(ctx, i);
    452 
    453         if(ctx->mHwcDebug[i]) {
    454             delete ctx->mHwcDebug[i];
    455             ctx->mHwcDebug[i] = NULL;
    456         }
    457         if(ctx->mLayerRotMap[i]) {
    458             delete ctx->mLayerRotMap[i];
    459             ctx->mLayerRotMap[i] = NULL;
    460         }
    461     }
    462     if(ctx->mHWCVirtual) {
    463         delete ctx->mHWCVirtual;
    464         ctx->mHWCVirtual = NULL;
    465     }
    466     if(ctx->mAD) {
    467         delete ctx->mAD;
    468         ctx->mAD = NULL;
    469     }
    470 
    471 
    472 }
    473 
    474 //Helper to roundoff the refreshrates
    475 uint32_t roundOff(uint32_t refreshRate) {
    476     int count =  (int) (sizeof(stdRefreshRates)/sizeof(stdRefreshRates[0]));
    477     uint32_t rate = refreshRate;
    478     for(int i=0; i< count; i++) {
    479         if(abs(stdRefreshRates[i] - refreshRate) < 2) {
    480             // Most likely used for video, the fps can fluctuate
    481             // Ex: b/w 29 and 30 for 30 fps clip
    482             rate = stdRefreshRates[i];
    483             break;
    484         }
    485     }
    486     return rate;
    487 }
    488 
    489 //Helper func to set the dyn fps
    490 void setRefreshRate(hwc_context_t* ctx, int dpy, uint32_t refreshRate) {
    491     //Update only if different
    492     if(!ctx || refreshRate == ctx->dpyAttr[dpy].dynRefreshRate)
    493         return;
    494     const int fbNum = Overlay::getFbForDpy(dpy);
    495     char sysfsPath[qdutils::MAX_SYSFS_FILE_PATH];
    496     snprintf (sysfsPath, sizeof(sysfsPath),
    497             "/sys/devices/virtual/graphics/fb%d/dynamic_fps", fbNum);
    498 
    499     int fd = open(sysfsPath, O_WRONLY);
    500     if(fd >= 0) {
    501         char str[64];
    502         snprintf(str, sizeof(str), "%d", refreshRate);
    503         ssize_t ret = write(fd, str, strlen(str));
    504         if(ret < 0) {
    505             ALOGE("%s: Failed to write %d with error %s",
    506                     __FUNCTION__, refreshRate, strerror(errno));
    507         } else {
    508             ctx->dpyAttr[dpy].dynRefreshRate = refreshRate;
    509             ALOGD_IF(HWC_UTILS_DEBUG, "%s: Wrote %d to dynamic_fps",
    510                      __FUNCTION__, refreshRate);
    511         }
    512         close(fd);
    513     } else {
    514         ALOGE("%s: Failed to open %s with error %s", __FUNCTION__, sysfsPath,
    515               strerror(errno));
    516     }
    517 }
    518 
    519 void dumpsys_log(android::String8& buf, const char* fmt, ...)
    520 {
    521     va_list varargs;
    522     va_start(varargs, fmt);
    523     buf.appendFormatV(fmt, varargs);
    524     va_end(varargs);
    525 }
    526 
    527 int getExtOrientation(hwc_context_t* ctx) {
    528     int extOrient = ctx->mExtOrientation;
    529     if(ctx->mBufferMirrorMode)
    530         extOrient = getMirrorModeOrientation(ctx);
    531     return extOrient;
    532 }
    533 
    534 /* Calculates the destination position based on the action safe rectangle */
    535 void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& rect) {
    536     // Position
    537     int x = rect.left, y = rect.top;
    538     int w = rect.right - rect.left;
    539     int h = rect.bottom - rect.top;
    540 
    541     if(!ctx->dpyAttr[dpy].mActionSafePresent)
    542         return;
    543    // Read action safe properties
    544     int asWidthRatio = ctx->dpyAttr[dpy].mAsWidthRatio;
    545     int asHeightRatio = ctx->dpyAttr[dpy].mAsHeightRatio;
    546 
    547     float wRatio = 1.0;
    548     float hRatio = 1.0;
    549     float xRatio = 1.0;
    550     float yRatio = 1.0;
    551 
    552     uint32_t fbWidth = ctx->dpyAttr[dpy].xres;
    553     uint32_t fbHeight = ctx->dpyAttr[dpy].yres;
    554     if(ctx->dpyAttr[dpy].mMDPScalingMode) {
    555         // if MDP scaling mode is enabled for external, need to query
    556         // the actual width and height, as that is the physical w & h
    557          ctx->mHDMIDisplay->getAttributes(fbWidth, fbHeight);
    558     }
    559 
    560 
    561     // Since external is rotated 90, need to swap width/height
    562     int extOrient = getExtOrientation(ctx);
    563 
    564     if(extOrient & HWC_TRANSFORM_ROT_90)
    565         swap(fbWidth, fbHeight);
    566 
    567     float asX = 0;
    568     float asY = 0;
    569     float asW = (float)fbWidth;
    570     float asH = (float)fbHeight;
    571 
    572     // based on the action safe ratio, get the Action safe rectangle
    573     asW = ((float)fbWidth * (1.0f -  (float)asWidthRatio / 100.0f));
    574     asH = ((float)fbHeight * (1.0f -  (float)asHeightRatio / 100.0f));
    575     asX = ((float)fbWidth - asW) / 2;
    576     asY = ((float)fbHeight - asH) / 2;
    577 
    578     // calculate the position ratio
    579     xRatio = (float)x/(float)fbWidth;
    580     yRatio = (float)y/(float)fbHeight;
    581     wRatio = (float)w/(float)fbWidth;
    582     hRatio = (float)h/(float)fbHeight;
    583 
    584     //Calculate the position...
    585     x = int((xRatio * asW) + asX);
    586     y = int((yRatio * asH) + asY);
    587     w = int(wRatio * asW);
    588     h = int(hRatio * asH);
    589 
    590     // Convert it back to hwc_rect_t
    591     rect.left = x;
    592     rect.top = y;
    593     rect.right = w + rect.left;
    594     rect.bottom = h + rect.top;
    595 
    596     return;
    597 }
    598 
    599 // This function gets the destination position for Seconday display
    600 // based on the position and aspect ratio with orientation
    601 void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
    602                             hwc_rect_t& inRect, hwc_rect_t& outRect) {
    603     // Physical display resolution
    604     float fbWidth  = (float)ctx->dpyAttr[dpy].xres;
    605     float fbHeight = (float)ctx->dpyAttr[dpy].yres;
    606     //display position(x,y,w,h) in correct aspectratio after rotation
    607     int xPos = 0;
    608     int yPos = 0;
    609     float width = fbWidth;
    610     float height = fbHeight;
    611     // Width/Height used for calculation, after rotation
    612     float actualWidth = fbWidth;
    613     float actualHeight = fbHeight;
    614 
    615     float wRatio = 1.0;
    616     float hRatio = 1.0;
    617     float xRatio = 1.0;
    618     float yRatio = 1.0;
    619     hwc_rect_t rect = {0, 0, (int)fbWidth, (int)fbHeight};
    620 
    621     Dim inPos(inRect.left, inRect.top, inRect.right - inRect.left,
    622                 inRect.bottom - inRect.top);
    623     Dim outPos(outRect.left, outRect.top, outRect.right - outRect.left,
    624                 outRect.bottom - outRect.top);
    625 
    626     Whf whf((uint32_t)fbWidth, (uint32_t)fbHeight, 0);
    627     eTransform extorient = static_cast<eTransform>(extOrientation);
    628     // To calculate the destination co-ordinates in the new orientation
    629     preRotateSource(extorient, whf, inPos);
    630 
    631     if(extOrientation & HAL_TRANSFORM_ROT_90) {
    632         // Swap width/height for input position
    633         swapWidthHeight(actualWidth, actualHeight);
    634         qdutils::getAspectRatioPosition((int)fbWidth, (int)fbHeight,
    635                                 (int)actualWidth, (int)actualHeight, rect);
    636         xPos = rect.left;
    637         yPos = rect.top;
    638         width = float(rect.right - rect.left);
    639         height = float(rect.bottom - rect.top);
    640     }
    641     xRatio = (float)((float)inPos.x/actualWidth);
    642     yRatio = (float)((float)inPos.y/actualHeight);
    643     wRatio = (float)((float)inPos.w/actualWidth);
    644     hRatio = (float)((float)inPos.h/actualHeight);
    645 
    646     //Calculate the pos9ition...
    647     outPos.x = uint32_t((xRatio * width) + (float)xPos);
    648     outPos.y = uint32_t((yRatio * height) + (float)yPos);
    649     outPos.w = uint32_t(wRatio * width);
    650     outPos.h = uint32_t(hRatio * height);
    651     ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio Position: x = %d,"
    652                  "y = %d w = %d h = %d", __FUNCTION__, outPos.x, outPos.y,
    653                  outPos.w, outPos.h);
    654 
    655     // For sidesync, the dest fb will be in portrait orientation, and the crop
    656     // will be updated to avoid the black side bands, and it will be upscaled
    657     // to fit the dest RB, so recalculate
    658     // the position based on the new width and height
    659     if ((extOrientation & HWC_TRANSFORM_ROT_90) &&
    660                         isOrientationPortrait(ctx)) {
    661         hwc_rect_t r = {0, 0, 0, 0};
    662         //Calculate the position
    663         xRatio = (float)(outPos.x - xPos)/width;
    664         // GetaspectRatio -- tricky to get the correct aspect ratio
    665         // But we need to do this.
    666         qdutils::getAspectRatioPosition((int)width, (int)height,
    667                                (int)width,(int)height, r);
    668         xPos = r.left;
    669         yPos = r.top;
    670         float tempHeight = float(r.bottom - r.top);
    671         yRatio = (float)yPos/height;
    672         wRatio = (float)outPos.w/width;
    673         hRatio = tempHeight/height;
    674 
    675         //Map the coordinates back to Framebuffer domain
    676         outPos.x = uint32_t(xRatio * fbWidth);
    677         outPos.y = uint32_t(yRatio * fbHeight);
    678         outPos.w = uint32_t(wRatio * fbWidth);
    679         outPos.h = uint32_t(hRatio * fbHeight);
    680 
    681         ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio for device in"
    682                  "portrait: x = %d,y = %d w = %d h = %d", __FUNCTION__,
    683                  outPos.x, outPos.y,
    684                  outPos.w, outPos.h);
    685     }
    686     if(ctx->dpyAttr[dpy].mMDPScalingMode) {
    687         uint32_t extW = 0, extH = 0;
    688         if(dpy == HWC_DISPLAY_EXTERNAL) {
    689             ctx->mHDMIDisplay->getAttributes(extW, extH);
    690         } else if(dpy == HWC_DISPLAY_VIRTUAL) {
    691             extW = ctx->mHWCVirtual->getScalingWidth();
    692             extH = ctx->mHWCVirtual->getScalingHeight();
    693         }
    694         ALOGD_IF(HWC_UTILS_DEBUG, "%s: Scaling mode extW=%d extH=%d",
    695                 __FUNCTION__, extW, extH);
    696 
    697         fbWidth  = (float)ctx->dpyAttr[dpy].xres;
    698         fbHeight = (float)ctx->dpyAttr[dpy].yres;
    699         //Calculate the position...
    700         xRatio = (float)outPos.x/fbWidth;
    701         yRatio = (float)outPos.y/fbHeight;
    702         wRatio = (float)outPos.w/fbWidth;
    703         hRatio = (float)outPos.h/fbHeight;
    704 
    705         outPos.x = uint32_t(xRatio * (float)extW);
    706         outPos.y = uint32_t(yRatio * (float)extH);
    707         outPos.w = uint32_t(wRatio * (float)extW);
    708         outPos.h = uint32_t(hRatio * (float)extH);
    709     }
    710     // Convert Dim to hwc_rect_t
    711     outRect.left = outPos.x;
    712     outRect.top = outPos.y;
    713     outRect.right = outPos.x + outPos.w;
    714     outRect.bottom = outPos.y + outPos.h;
    715 
    716     return;
    717 }
    718 
    719 bool isPrimaryPortrait(hwc_context_t *ctx) {
    720     int fbWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
    721     int fbHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
    722     if(fbWidth < fbHeight) {
    723         return true;
    724     }
    725     return false;
    726 }
    727 
    728 bool isOrientationPortrait(hwc_context_t *ctx) {
    729     if(isPrimaryPortrait(ctx)) {
    730         return !(ctx->deviceOrientation & 0x1);
    731     }
    732     return (ctx->deviceOrientation & 0x1);
    733 }
    734 
    735 void calcExtDisplayPosition(hwc_context_t *ctx,
    736                                private_handle_t *hnd,
    737                                int dpy,
    738                                hwc_rect_t& sourceCrop,
    739                                hwc_rect_t& displayFrame,
    740                                int& transform,
    741                                ovutils::eTransform& orient) {
    742     // Swap width and height when there is a 90deg transform
    743     int extOrient = getExtOrientation(ctx);
    744     if(dpy && ctx->mOverlay->isUIScalingOnExternalSupported()) {
    745         if(!isYuvBuffer(hnd)) {
    746             if(extOrient & HWC_TRANSFORM_ROT_90) {
    747                 int dstWidth = ctx->dpyAttr[dpy].xres;
    748                 int dstHeight = ctx->dpyAttr[dpy].yres;;
    749                 int srcWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
    750                 int srcHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
    751                 if(!isPrimaryPortrait(ctx)) {
    752                     swap(srcWidth, srcHeight);
    753                 }                    // Get Aspect Ratio for external
    754                 qdutils::getAspectRatioPosition(dstWidth, dstHeight, srcWidth,
    755                                     srcHeight, displayFrame);
    756                 // Crop - this is needed, because for sidesync, the dest fb will
    757                 // be in portrait orientation, so update the crop to not show the
    758                 // black side bands.
    759                 if (isOrientationPortrait(ctx)) {
    760                     sourceCrop = displayFrame;
    761                     displayFrame.left = 0;
    762                     displayFrame.top = 0;
    763                     displayFrame.right = dstWidth;
    764                     displayFrame.bottom = dstHeight;
    765                 }
    766             }
    767             if(ctx->dpyAttr[dpy].mMDPScalingMode) {
    768                 uint32_t extW = 0, extH = 0;
    769                 // if MDP scaling mode is enabled, map the co-ordinates to new
    770                 // domain(downscaled)
    771                 float fbWidth  = (float)ctx->dpyAttr[dpy].xres;
    772                 float fbHeight = (float)ctx->dpyAttr[dpy].yres;
    773                 // query MDP configured attributes
    774                 if(dpy == HWC_DISPLAY_EXTERNAL) {
    775                     ctx->mHDMIDisplay->getAttributes(extW, extH);
    776                 } else if(dpy == HWC_DISPLAY_VIRTUAL) {
    777                     extW = ctx->mHWCVirtual->getScalingWidth();
    778                     extH = ctx->mHWCVirtual->getScalingHeight();
    779                 }
    780                 ALOGD_IF(HWC_UTILS_DEBUG, "%s: Scaling mode extW=%d extH=%d",
    781                         __FUNCTION__, extW, extH);
    782 
    783                 //Calculate the ratio...
    784                 float wRatio = ((float)extW)/fbWidth;
    785                 float hRatio = ((float)extH)/fbHeight;
    786 
    787                 //convert Dim to hwc_rect_t
    788                 displayFrame.left = int(wRatio*(float)displayFrame.left);
    789                 displayFrame.top = int(hRatio*(float)displayFrame.top);
    790                 displayFrame.right = int(wRatio*(float)displayFrame.right);
    791                 displayFrame.bottom = int(hRatio*(float)displayFrame.bottom);
    792                 ALOGD_IF(DEBUG_MDPDOWNSCALE, "Calculated external display frame"
    793                          " for MDPDownscale feature [%d %d %d %d]",
    794                          displayFrame.left, displayFrame.top,
    795                          displayFrame.right, displayFrame.bottom);
    796             }
    797         }else {
    798             if(extOrient || ctx->dpyAttr[dpy].mMDPScalingMode) {
    799                 getAspectRatioPosition(ctx, dpy, extOrient,
    800                                        displayFrame, displayFrame);
    801             }
    802         }
    803         // If there is a external orientation set, use that
    804         if(extOrient) {
    805             transform = extOrient;
    806             orient = static_cast<ovutils::eTransform >(extOrient);
    807         }
    808         // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
    809         getActionSafePosition(ctx, dpy, displayFrame);
    810     }
    811 }
    812 
    813 /* Returns the orientation which needs to be set on External for
    814  *  SideSync/Buffer Mirrormode
    815  */
    816 int getMirrorModeOrientation(hwc_context_t *ctx) {
    817     int extOrientation = 0;
    818     int deviceOrientation = ctx->deviceOrientation;
    819     if(!isPrimaryPortrait(ctx))
    820         deviceOrientation = (deviceOrientation + 1) % 4;
    821      if (deviceOrientation == 0)
    822          extOrientation = HWC_TRANSFORM_ROT_270;
    823      else if (deviceOrientation == 1)//90
    824          extOrientation = 0;
    825      else if (deviceOrientation == 2)//180
    826          extOrientation = HWC_TRANSFORM_ROT_90;
    827      else if (deviceOrientation == 3)//270
    828          extOrientation = HWC_TRANSFORM_FLIP_V | HWC_TRANSFORM_FLIP_H;
    829 
    830     return extOrientation;
    831 }
    832 
    833 /* Get External State names */
    834 const char* getExternalDisplayState(uint32_t external_state) {
    835     static const char* externalStates[EXTERNAL_MAXSTATES] = {0};
    836     externalStates[EXTERNAL_OFFLINE] = STR(EXTERNAL_OFFLINE);
    837     externalStates[EXTERNAL_ONLINE]  = STR(EXTERNAL_ONLINE);
    838     externalStates[EXTERNAL_PAUSE]   = STR(EXTERNAL_PAUSE);
    839     externalStates[EXTERNAL_RESUME]  = STR(EXTERNAL_RESUME);
    840 
    841     if(external_state >= EXTERNAL_MAXSTATES) {
    842         return "EXTERNAL_INVALID";
    843     }
    844 
    845     return externalStates[external_state];
    846 }
    847 
    848 bool isDownscaleRequired(hwc_layer_1_t const* layer) {
    849     hwc_rect_t displayFrame  = layer->displayFrame;
    850     hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
    851     int dst_w, dst_h, src_w, src_h;
    852     dst_w = displayFrame.right - displayFrame.left;
    853     dst_h = displayFrame.bottom - displayFrame.top;
    854     src_w = sourceCrop.right - sourceCrop.left;
    855     src_h = sourceCrop.bottom - sourceCrop.top;
    856 
    857     if(((src_w > dst_w) || (src_h > dst_h)))
    858         return true;
    859 
    860     return false;
    861 }
    862 bool needsScaling(hwc_layer_1_t const* layer) {
    863     int dst_w, dst_h, src_w, src_h;
    864     hwc_rect_t displayFrame  = layer->displayFrame;
    865     hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
    866 
    867     dst_w = displayFrame.right - displayFrame.left;
    868     dst_h = displayFrame.bottom - displayFrame.top;
    869     src_w = sourceCrop.right - sourceCrop.left;
    870     src_h = sourceCrop.bottom - sourceCrop.top;
    871 
    872     if(layer->transform & HWC_TRANSFORM_ROT_90)
    873         swap(src_w, src_h);
    874 
    875     if(((src_w != dst_w) || (src_h != dst_h)))
    876         return true;
    877 
    878     return false;
    879 }
    880 
    881 // Checks if layer needs scaling with split
    882 bool needsScalingWithSplit(hwc_context_t* ctx, hwc_layer_1_t const* layer,
    883         const int& dpy) {
    884 
    885     int src_width_l, src_height_l;
    886     int src_width_r, src_height_r;
    887     int dst_width_l, dst_height_l;
    888     int dst_width_r, dst_height_r;
    889     int hw_w = ctx->dpyAttr[dpy].xres;
    890     int hw_h = ctx->dpyAttr[dpy].yres;
    891     hwc_rect_t cropL, dstL, cropR, dstR;
    892     const int lSplit = getLeftSplit(ctx, dpy);
    893     hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
    894     hwc_rect_t displayFrame  = layer->displayFrame;
    895     private_handle_t *hnd = (private_handle_t *)layer->handle;
    896 
    897     cropL = sourceCrop;
    898     dstL = displayFrame;
    899     hwc_rect_t scissorL = { 0, 0, lSplit, hw_h };
    900     scissorL = getIntersection(ctx->mViewFrame[dpy], scissorL);
    901     qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0);
    902 
    903     cropR = sourceCrop;
    904     dstR = displayFrame;
    905     hwc_rect_t scissorR = { lSplit, 0, hw_w, hw_h };
    906     scissorR = getIntersection(ctx->mViewFrame[dpy], scissorR);
    907     qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0);
    908 
    909     // Sanitize Crop to stitch
    910     sanitizeSourceCrop(cropL, cropR, hnd);
    911 
    912     // Calculate the left dst
    913     dst_width_l = dstL.right - dstL.left;
    914     dst_height_l = dstL.bottom - dstL.top;
    915     src_width_l = cropL.right - cropL.left;
    916     src_height_l = cropL.bottom - cropL.top;
    917 
    918     // check if there is any scaling on the left
    919     if(((src_width_l != dst_width_l) || (src_height_l != dst_height_l)))
    920         return true;
    921 
    922     // Calculate the right dst
    923     dst_width_r = dstR.right - dstR.left;
    924     dst_height_r = dstR.bottom - dstR.top;
    925     src_width_r = cropR.right - cropR.left;
    926     src_height_r = cropR.bottom - cropR.top;
    927 
    928     // check if there is any scaling on the right
    929     if(((src_width_r != dst_width_r) || (src_height_r != dst_height_r)))
    930         return true;
    931 
    932     return false;
    933 }
    934 
    935 bool isAlphaScaled(hwc_layer_1_t const* layer) {
    936     if(needsScaling(layer) && isAlphaPresent(layer)) {
    937         return true;
    938     }
    939     return false;
    940 }
    941 
    942 bool isAlphaPresent(hwc_layer_1_t const* layer) {
    943     private_handle_t *hnd = (private_handle_t *)layer->handle;
    944     if(hnd) {
    945         int format = hnd->format;
    946         switch(format) {
    947         case HAL_PIXEL_FORMAT_RGBA_8888:
    948         case HAL_PIXEL_FORMAT_BGRA_8888:
    949             // In any more formats with Alpha go here..
    950             return true;
    951         default : return false;
    952         }
    953     }
    954     return false;
    955 }
    956 
    957 static void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
    958         hwc_rect_t& crop, hwc_rect_t& dst) {
    959     int hw_w = ctx->dpyAttr[dpy].xres;
    960     int hw_h = ctx->dpyAttr[dpy].yres;
    961     if(dst.left < 0 || dst.top < 0 ||
    962             dst.right > hw_w || dst.bottom > hw_h) {
    963         hwc_rect_t scissor = {0, 0, hw_w, hw_h };
    964         scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
    965         qhwc::calculate_crop_rects(crop, dst, scissor, transform);
    966     }
    967 }
    968 
    969 static void trimList(hwc_context_t *ctx, hwc_display_contents_1_t *list,
    970         const int& dpy) {
    971     for(uint32_t i = 0; i < list->numHwLayers - 1; i++) {
    972         hwc_layer_1_t *layer = &list->hwLayers[i];
    973         hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
    974         int transform = (list->hwLayers[i].flags & HWC_COLOR_FILL) ? 0 :
    975                 list->hwLayers[i].transform;
    976         trimLayer(ctx, dpy,
    977                 transform,
    978                 (hwc_rect_t&)crop,
    979                 (hwc_rect_t&)list->hwLayers[i].displayFrame);
    980         layer->sourceCropf.left = (float)crop.left;
    981         layer->sourceCropf.right = (float)crop.right;
    982         layer->sourceCropf.top = (float)crop.top;
    983         layer->sourceCropf.bottom = (float)crop.bottom;
    984     }
    985 }
    986 
    987 void setListStats(hwc_context_t *ctx,
    988         hwc_display_contents_1_t *list, int dpy) {
    989     const int prevYuvCount = ctx->listStats[dpy].yuvCount;
    990     memset(&ctx->listStats[dpy], 0, sizeof(ListStats));
    991     ctx->listStats[dpy].numAppLayers = (int)list->numHwLayers - 1;
    992     ctx->listStats[dpy].fbLayerIndex = (int)list->numHwLayers - 1;
    993     ctx->listStats[dpy].skipCount = 0;
    994     ctx->listStats[dpy].preMultipliedAlpha = false;
    995     ctx->listStats[dpy].isSecurePresent = false;
    996     ctx->listStats[dpy].yuvCount = 0;
    997     char property[PROPERTY_VALUE_MAX];
    998     ctx->listStats[dpy].isDisplayAnimating = false;
    999     ctx->listStats[dpy].secureUI = false;
   1000     ctx->listStats[dpy].yuv4k2kCount = 0;
   1001     ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
   1002     ctx->listStats[dpy].renderBufIndexforABC = -1;
   1003     ctx->listStats[dpy].secureRGBCount = 0;
   1004     ctx->listStats[dpy].refreshRateRequest = ctx->dpyAttr[dpy].refreshRate;
   1005     uint32_t refreshRate = 0;
   1006     qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
   1007 
   1008     ctx->listStats[dpy].mAIVVideoMode = false;
   1009     resetROI(ctx, dpy);
   1010 
   1011     trimList(ctx, list, dpy);
   1012     optimizeLayerRects(list);
   1013     for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
   1014         hwc_layer_1_t const* layer = &list->hwLayers[i];
   1015         private_handle_t *hnd = (private_handle_t *)layer->handle;
   1016 
   1017 #ifdef QCOM_BSP
   1018         // Window boxing feature is applicable obly for external display, So
   1019         // enable mAIVVideoMode only for external display
   1020         if(ctx->mWindowboxFeature && dpy && isAIVVideoLayer(layer)) {
   1021             ctx->listStats[dpy].mAIVVideoMode = true;
   1022         }
   1023         if (layer->flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
   1024             ctx->listStats[dpy].isDisplayAnimating = true;
   1025         }
   1026         if(isSecureDisplayBuffer(hnd)) {
   1027             ctx->listStats[dpy].secureUI = true;
   1028         }
   1029 #endif
   1030         // continue if number of app layers exceeds MAX_NUM_APP_LAYERS
   1031         if(ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS)
   1032             continue;
   1033 
   1034         //reset yuv indices
   1035         ctx->listStats[dpy].yuvIndices[i] = -1;
   1036         ctx->listStats[dpy].yuv4k2kIndices[i] = -1;
   1037 
   1038         if (isSecureBuffer(hnd)) {
   1039             ctx->listStats[dpy].isSecurePresent = true;
   1040             if(not isYuvBuffer(hnd)) {
   1041                 // cache secureRGB layer parameters like we cache for YUV layers
   1042                 int& secureRGBCount = ctx->listStats[dpy].secureRGBCount;
   1043                 ctx->listStats[dpy].secureRGBIndices[secureRGBCount] = (int)i;
   1044                 secureRGBCount++;
   1045             }
   1046         }
   1047 
   1048         if (isSkipLayer(&list->hwLayers[i])) {
   1049             ctx->listStats[dpy].skipCount++;
   1050         }
   1051 
   1052         if (UNLIKELY(isYuvBuffer(hnd))) {
   1053             int& yuvCount = ctx->listStats[dpy].yuvCount;
   1054             ctx->listStats[dpy].yuvIndices[yuvCount] = (int)i;
   1055             yuvCount++;
   1056 
   1057             if(UNLIKELY(isYUVSplitNeeded(hnd))){
   1058                 int& yuv4k2kCount = ctx->listStats[dpy].yuv4k2kCount;
   1059                 ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = (int)i;
   1060                 yuv4k2kCount++;
   1061             }
   1062         }
   1063         if(layer->blending == HWC_BLENDING_PREMULT)
   1064             ctx->listStats[dpy].preMultipliedAlpha = true;
   1065 
   1066 #ifdef DYNAMIC_FPS
   1067         if (!dpy && mdpHw.isDynFpsSupported() && ctx->mUseMetaDataRefreshRate){
   1068             //dyn fps: get refreshrate from metadata
   1069             //Support multiple refresh rates if they are same
   1070             //else set to  default
   1071             MetaData_t *mdata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
   1072             if (mdata && (mdata->operation & UPDATE_REFRESH_RATE)) {
   1073                 // Valid refreshRate in metadata and within the range
   1074                 uint32_t rate = roundOff(mdata->refreshrate);
   1075                 if((rate >= mdpHw.getMinFpsSupported() &&
   1076                                 rate <= mdpHw.getMaxFpsSupported())) {
   1077                     if (!refreshRate) {
   1078                         refreshRate = rate;
   1079                     } else if(refreshRate != rate) {
   1080                         // multiple refreshrate requests, set to default
   1081                         refreshRate = ctx->dpyAttr[dpy].refreshRate;
   1082                     }
   1083                 }
   1084             }
   1085         }
   1086 #endif
   1087     }
   1088     if(ctx->listStats[dpy].yuvCount > 0) {
   1089         if (property_get("hw.cabl.yuv", property, NULL) > 0) {
   1090             if (atoi(property) != 1) {
   1091                 property_set("hw.cabl.yuv", "1");
   1092             }
   1093         }
   1094     } else {
   1095         if (property_get("hw.cabl.yuv", property, NULL) > 0) {
   1096             if (atoi(property) != 0) {
   1097                 property_set("hw.cabl.yuv", "0");
   1098             }
   1099         }
   1100     }
   1101 
   1102     //The marking of video begin/end is useful on some targets where we need
   1103     //to have a padding round to be able to shift pipes across mixers.
   1104     if(prevYuvCount != ctx->listStats[dpy].yuvCount) {
   1105         ctx->mVideoTransFlag = true;
   1106     }
   1107 
   1108     if(dpy == HWC_DISPLAY_PRIMARY) {
   1109         ctx->mAD->markDoable(ctx, list);
   1110         //Store the requested fresh rate
   1111         ctx->listStats[dpy].refreshRateRequest = refreshRate ?
   1112                                 refreshRate : ctx->dpyAttr[dpy].refreshRate;
   1113     }
   1114 }
   1115 
   1116 
   1117 static void calc_cut(double& leftCutRatio, double& topCutRatio,
   1118         double& rightCutRatio, double& bottomCutRatio, int orient) {
   1119     if(orient & HAL_TRANSFORM_FLIP_H) {
   1120         swap(leftCutRatio, rightCutRatio);
   1121     }
   1122     if(orient & HAL_TRANSFORM_FLIP_V) {
   1123         swap(topCutRatio, bottomCutRatio);
   1124     }
   1125     if(orient & HAL_TRANSFORM_ROT_90) {
   1126         //Anti clock swapping
   1127         double tmpCutRatio = leftCutRatio;
   1128         leftCutRatio = topCutRatio;
   1129         topCutRatio = rightCutRatio;
   1130         rightCutRatio = bottomCutRatio;
   1131         bottomCutRatio = tmpCutRatio;
   1132     }
   1133 }
   1134 
   1135 bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer) {
   1136     if((ctx->mMDP.version < qdutils::MDSS_V5) &&
   1137        (ctx->mMDP.version > qdutils::MDP_V3_0) &&
   1138         ctx->mSecuring) {
   1139         return true;
   1140     }
   1141     if (isSecureModePolicy(ctx->mMDP.version)) {
   1142         private_handle_t *hnd = (private_handle_t *)layer->handle;
   1143         if(ctx->mSecureMode) {
   1144             if (! isSecureBuffer(hnd)) {
   1145                 ALOGD_IF(HWC_UTILS_DEBUG,"%s:Securing Turning ON ...",
   1146                          __FUNCTION__);
   1147                 return true;
   1148             }
   1149         } else {
   1150             if (isSecureBuffer(hnd)) {
   1151                 ALOGD_IF(HWC_UTILS_DEBUG,"%s:Securing Turning OFF ...",
   1152                          __FUNCTION__);
   1153                 return true;
   1154             }
   1155         }
   1156     }
   1157     return false;
   1158 }
   1159 
   1160 bool isSecureModePolicy(int mdpVersion) {
   1161     if (mdpVersion < qdutils::MDSS_V5)
   1162         return true;
   1163     else
   1164         return false;
   1165 }
   1166 
   1167 bool isRotatorSupportedFormat(private_handle_t *hnd) {
   1168     // Following rotator src formats are supported by mdp driver
   1169     // TODO: Add more formats in future, if mdp driver adds support
   1170     if(hnd != NULL) {
   1171         switch(hnd->format) {
   1172             case HAL_PIXEL_FORMAT_RGBA_8888:
   1173             case HAL_PIXEL_FORMAT_RGBA_5551:
   1174             case HAL_PIXEL_FORMAT_RGBA_4444:
   1175             case HAL_PIXEL_FORMAT_RGB_565:
   1176             case HAL_PIXEL_FORMAT_RGB_888:
   1177             case HAL_PIXEL_FORMAT_BGRA_8888:
   1178                 return true;
   1179             default:
   1180                 return false;
   1181         }
   1182     }
   1183     return false;
   1184 }
   1185 
   1186 bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd) {
   1187     // Rotate layers, if it is not secure display buffer and not
   1188     // for the MDP versions below MDP5
   1189     if((!isSecureDisplayBuffer(hnd) && isRotatorSupportedFormat(hnd) &&
   1190         !ctx->mMDP.version < qdutils::MDSS_V5)
   1191                    || isYuvBuffer(hnd)) {
   1192         return true;
   1193     }
   1194     return false;
   1195 }
   1196 
   1197 // returns true if Action safe dimensions are set and target supports Actionsafe
   1198 bool isActionSafePresent(hwc_context_t *ctx, int dpy) {
   1199     // if external supports underscan, do nothing
   1200     // it will be taken care in the driver
   1201     // Disable Action safe for 8974 due to HW limitation for downscaling
   1202     // layers with overlapped region
   1203     // Disable Actionsafe for non HDMI displays.
   1204     if(!(dpy == HWC_DISPLAY_EXTERNAL) ||
   1205         qdutils::MDPVersion::getInstance().is8x74v2() ||
   1206         ctx->mHDMIDisplay->isCEUnderscanSupported()) {
   1207         return false;
   1208     }
   1209 
   1210     char value[PROPERTY_VALUE_MAX];
   1211     // Read action safe properties
   1212     property_get("persist.sys.actionsafe.width", value, "0");
   1213     ctx->dpyAttr[dpy].mAsWidthRatio = atoi(value);
   1214     property_get("persist.sys.actionsafe.height", value, "0");
   1215     ctx->dpyAttr[dpy].mAsHeightRatio = atoi(value);
   1216 
   1217     if(!ctx->dpyAttr[dpy].mAsWidthRatio && !ctx->dpyAttr[dpy].mAsHeightRatio) {
   1218         //No action safe ratio set, return
   1219         return false;
   1220     }
   1221     return true;
   1222 }
   1223 
   1224 int getBlending(int blending) {
   1225     switch(blending) {
   1226     case HWC_BLENDING_NONE:
   1227         return overlay::utils::OVERLAY_BLENDING_OPAQUE;
   1228     case HWC_BLENDING_PREMULT:
   1229         return overlay::utils::OVERLAY_BLENDING_PREMULT;
   1230     case HWC_BLENDING_COVERAGE :
   1231     default:
   1232         return overlay::utils::OVERLAY_BLENDING_COVERAGE;
   1233     }
   1234 }
   1235 
   1236 //Crops source buffer against destination and FB boundaries
   1237 void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
   1238                           const hwc_rect_t& scissor, int orient) {
   1239 
   1240     int& crop_l = crop.left;
   1241     int& crop_t = crop.top;
   1242     int& crop_r = crop.right;
   1243     int& crop_b = crop.bottom;
   1244     int crop_w = crop.right - crop.left;
   1245     int crop_h = crop.bottom - crop.top;
   1246 
   1247     int& dst_l = dst.left;
   1248     int& dst_t = dst.top;
   1249     int& dst_r = dst.right;
   1250     int& dst_b = dst.bottom;
   1251     int dst_w = abs(dst.right - dst.left);
   1252     int dst_h = abs(dst.bottom - dst.top);
   1253 
   1254     const int& sci_l = scissor.left;
   1255     const int& sci_t = scissor.top;
   1256     const int& sci_r = scissor.right;
   1257     const int& sci_b = scissor.bottom;
   1258 
   1259     double leftCutRatio = 0.0, rightCutRatio = 0.0, topCutRatio = 0.0,
   1260             bottomCutRatio = 0.0;
   1261 
   1262     if(dst_l < sci_l) {
   1263         leftCutRatio = (double)(sci_l - dst_l) / (double)dst_w;
   1264         dst_l = sci_l;
   1265     }
   1266 
   1267     if(dst_r > sci_r) {
   1268         rightCutRatio = (double)(dst_r - sci_r) / (double)dst_w;
   1269         dst_r = sci_r;
   1270     }
   1271 
   1272     if(dst_t < sci_t) {
   1273         topCutRatio = (double)(sci_t - dst_t) / (double)dst_h;
   1274         dst_t = sci_t;
   1275     }
   1276 
   1277     if(dst_b > sci_b) {
   1278         bottomCutRatio = (double)(dst_b - sci_b) / (double)dst_h;
   1279         dst_b = sci_b;
   1280     }
   1281 
   1282     calc_cut(leftCutRatio, topCutRatio, rightCutRatio, bottomCutRatio, orient);
   1283     crop_l += (int)round((double)crop_w * leftCutRatio);
   1284     crop_t += (int)round((double)crop_h * topCutRatio);
   1285     crop_r -= (int)round((double)crop_w * rightCutRatio);
   1286     crop_b -= (int)round((double)crop_h * bottomCutRatio);
   1287 }
   1288 
   1289 bool areLayersIntersecting(const hwc_layer_1_t* layer1,
   1290         const hwc_layer_1_t* layer2) {
   1291     hwc_rect_t irect = getIntersection(layer1->displayFrame,
   1292             layer2->displayFrame);
   1293     return isValidRect(irect);
   1294 }
   1295 
   1296 bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2)
   1297 {
   1298    return ((rect1.left == rect2.left) && (rect1.top == rect2.top) &&
   1299            (rect1.right == rect2.right) && (rect1.bottom == rect2.bottom));
   1300 }
   1301 
   1302 bool isValidRect(const hwc_rect& rect)
   1303 {
   1304    return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
   1305 }
   1306 
   1307 bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs) {
   1308     if(lhs.left == rhs.left && lhs.top == rhs.top &&
   1309        lhs.right == rhs.right &&  lhs.bottom == rhs.bottom )
   1310           return true ;
   1311     return false;
   1312 }
   1313 
   1314 hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off)
   1315 {
   1316     hwc_rect_t res;
   1317 
   1318     if(!isValidRect(rect))
   1319         return (hwc_rect_t){0, 0, 0, 0};
   1320 
   1321     res.left = rect.left + x_off;
   1322     res.top = rect.top + y_off;
   1323     res.right = rect.right + x_off;
   1324     res.bottom = rect.bottom + y_off;
   1325 
   1326     return res;
   1327 }
   1328 
   1329 /* computes the intersection of two rects */
   1330 hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2)
   1331 {
   1332    hwc_rect_t res;
   1333 
   1334    if(!isValidRect(rect1) || !isValidRect(rect2)){
   1335       return (hwc_rect_t){0, 0, 0, 0};
   1336    }
   1337 
   1338 
   1339    res.left = max(rect1.left, rect2.left);
   1340    res.top = max(rect1.top, rect2.top);
   1341    res.right = min(rect1.right, rect2.right);
   1342    res.bottom = min(rect1.bottom, rect2.bottom);
   1343 
   1344    if(!isValidRect(res))
   1345       return (hwc_rect_t){0, 0, 0, 0};
   1346 
   1347    return res;
   1348 }
   1349 
   1350 /* computes the union of two rects */
   1351 hwc_rect_t getUnion(const hwc_rect &rect1, const hwc_rect &rect2)
   1352 {
   1353    hwc_rect_t res;
   1354 
   1355    if(!isValidRect(rect1)){
   1356       return rect2;
   1357    }
   1358 
   1359    if(!isValidRect(rect2)){
   1360       return rect1;
   1361    }
   1362 
   1363    res.left = min(rect1.left, rect2.left);
   1364    res.top = min(rect1.top, rect2.top);
   1365    res.right =  max(rect1.right, rect2.right);
   1366    res.bottom =  max(rect1.bottom, rect2.bottom);
   1367 
   1368    return res;
   1369 }
   1370 
   1371 /* Not a geometrical rect deduction. Deducts rect2 from rect1 only if it results
   1372  * a single rect */
   1373 hwc_rect_t deductRect(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
   1374 
   1375    hwc_rect_t res = rect1;
   1376 
   1377    if((rect1.left == rect2.left) && (rect1.right == rect2.right)) {
   1378       if((rect1.top == rect2.top) && (rect2.bottom <= rect1.bottom))
   1379          res.top = rect2.bottom;
   1380       else if((rect1.bottom == rect2.bottom)&& (rect2.top >= rect1.top))
   1381          res.bottom = rect2.top;
   1382    }
   1383    else if((rect1.top == rect2.top) && (rect1.bottom == rect2.bottom)) {
   1384       if((rect1.left == rect2.left) && (rect2.right <= rect1.right))
   1385          res.left = rect2.right;
   1386       else if((rect1.right == rect2.right)&& (rect2.left >= rect1.left))
   1387          res.right = rect2.left;
   1388    }
   1389    return res;
   1390 }
   1391 
   1392 void optimizeLayerRects(const hwc_display_contents_1_t *list) {
   1393     int i= (int)list->numHwLayers-2;
   1394     while(i > 0) {
   1395         //see if there is no blending required.
   1396         //If it is opaque see if we can substract this region from below
   1397         //layers.
   1398         if(list->hwLayers[i].blending == HWC_BLENDING_NONE &&
   1399                 list->hwLayers[i].planeAlpha == 0xFF) {
   1400             int j= i-1;
   1401             hwc_rect_t& topframe =
   1402                 (hwc_rect_t&)list->hwLayers[i].displayFrame;
   1403             while(j >= 0) {
   1404                if(!needsScaling(&list->hwLayers[j])) {
   1405                   hwc_layer_1_t* layer = (hwc_layer_1_t*)&list->hwLayers[j];
   1406                   hwc_rect_t& bottomframe = layer->displayFrame;
   1407                   hwc_rect_t bottomCrop =
   1408                       integerizeSourceCrop(layer->sourceCropf);
   1409                   int transform = (layer->flags & HWC_COLOR_FILL) ? 0 :
   1410                       layer->transform;
   1411 
   1412                   hwc_rect_t irect = getIntersection(bottomframe, topframe);
   1413                   if(isValidRect(irect)) {
   1414                      hwc_rect_t dest_rect;
   1415                      //if intersection is valid rect, deduct it
   1416                      dest_rect  = deductRect(bottomframe, irect);
   1417                      qhwc::calculate_crop_rects(bottomCrop, bottomframe,
   1418                                                 dest_rect, transform);
   1419                      //Update layer sourceCropf
   1420                      layer->sourceCropf.left =(float)bottomCrop.left;
   1421                      layer->sourceCropf.top = (float)bottomCrop.top;
   1422                      layer->sourceCropf.right = (float)bottomCrop.right;
   1423                      layer->sourceCropf.bottom = (float)bottomCrop.bottom;
   1424 #ifdef QCOM_BSP
   1425                      //Update layer dirtyRect
   1426                      layer->dirtyRect = getIntersection(bottomCrop,
   1427                                             layer->dirtyRect);
   1428 #endif
   1429                   }
   1430                }
   1431                j--;
   1432             }
   1433         }
   1434         i--;
   1435     }
   1436 }
   1437 
   1438 void getNonWormholeRegion(hwc_display_contents_1_t* list,
   1439                               hwc_rect_t& nwr)
   1440 {
   1441     size_t last = list->numHwLayers - 1;
   1442     hwc_rect_t fbDisplayFrame = list->hwLayers[last].displayFrame;
   1443     //Initiliaze nwr to first frame
   1444     nwr.left =  list->hwLayers[0].displayFrame.left;
   1445     nwr.top =  list->hwLayers[0].displayFrame.top;
   1446     nwr.right =  list->hwLayers[0].displayFrame.right;
   1447     nwr.bottom =  list->hwLayers[0].displayFrame.bottom;
   1448 
   1449     for (size_t i = 1; i < last; i++) {
   1450         hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
   1451         nwr = getUnion(nwr, displayFrame);
   1452     }
   1453 
   1454     //Intersect with the framebuffer
   1455     nwr = getIntersection(nwr, fbDisplayFrame);
   1456 }
   1457 
   1458 bool isExternalActive(hwc_context_t* ctx) {
   1459     return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
   1460 }
   1461 
   1462 void closeAcquireFds(hwc_display_contents_1_t* list) {
   1463     if(LIKELY(list)) {
   1464         for(uint32_t i = 0; i < list->numHwLayers; i++) {
   1465             //Close the acquireFenceFds
   1466             //HWC_FRAMEBUFFER are -1 already by SF, rest we close.
   1467             if(list->hwLayers[i].acquireFenceFd >= 0) {
   1468                 close(list->hwLayers[i].acquireFenceFd);
   1469                 list->hwLayers[i].acquireFenceFd = -1;
   1470             }
   1471         }
   1472         //Writeback
   1473         if(list->outbufAcquireFenceFd >= 0) {
   1474             close(list->outbufAcquireFenceFd);
   1475             list->outbufAcquireFenceFd = -1;
   1476         }
   1477     }
   1478 }
   1479 
   1480 int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
   1481         int fd) {
   1482     ATRACE_CALL();
   1483     int ret = 0;
   1484     int acquireFd[MAX_NUM_APP_LAYERS];
   1485     int count = 0;
   1486     int releaseFd = -1;
   1487     int retireFd = -1;
   1488     int fbFd = -1;
   1489     bool swapzero = false;
   1490 
   1491     struct mdp_buf_sync data;
   1492     memset(&data, 0, sizeof(data));
   1493     data.acq_fen_fd = acquireFd;
   1494     data.rel_fen_fd = &releaseFd;
   1495     data.retire_fen_fd = &retireFd;
   1496     data.flags = MDP_BUF_SYNC_FLAG_RETIRE_FENCE;
   1497 
   1498     char property[PROPERTY_VALUE_MAX];
   1499     if(property_get("debug.egl.swapinterval", property, "1") > 0) {
   1500         if(atoi(property) == 0)
   1501             swapzero = true;
   1502     }
   1503 
   1504     bool isExtAnimating = false;
   1505     if(dpy)
   1506        isExtAnimating = ctx->listStats[dpy].isDisplayAnimating;
   1507 
   1508     //Send acquireFenceFds to rotator
   1509     for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
   1510         int rotFd = ctx->mRotMgr->getRotDevFd();
   1511         int rotReleaseFd = -1;
   1512         overlay::Rotator* currRot = ctx->mLayerRotMap[dpy]->getRot(i);
   1513         hwc_layer_1_t* currLayer = ctx->mLayerRotMap[dpy]->getLayer(i);
   1514         if((currRot == NULL) || (currLayer == NULL)) {
   1515             continue;
   1516         }
   1517         struct mdp_buf_sync rotData;
   1518         memset(&rotData, 0, sizeof(rotData));
   1519         rotData.acq_fen_fd =
   1520                 &currLayer->acquireFenceFd;
   1521         rotData.rel_fen_fd = &rotReleaseFd; //driver to populate this
   1522         rotData.session_id = currRot->getSessId();
   1523         if(currLayer->acquireFenceFd >= 0) {
   1524             rotData.acq_fen_fd_cnt = 1; //1 ioctl call per rot session
   1525         }
   1526         int ret = 0;
   1527         if(LIKELY(!swapzero) and (not ctx->mLayerRotMap[dpy]->isRotCached(i)))
   1528             ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
   1529 
   1530         if(ret < 0) {
   1531             ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed for rot sync, err=%s",
   1532                     __FUNCTION__, strerror(errno));
   1533             close(rotReleaseFd);
   1534         } else {
   1535             close(currLayer->acquireFenceFd);
   1536             //For MDP to wait on.
   1537             currLayer->acquireFenceFd =
   1538                     dup(rotReleaseFd);
   1539             //A buffer is free to be used by producer as soon as its copied to
   1540             //rotator
   1541             currLayer->releaseFenceFd =
   1542                     rotReleaseFd;
   1543         }
   1544     }
   1545 
   1546     //Accumulate acquireFenceFds for MDP Overlays
   1547     if(list->outbufAcquireFenceFd >= 0) {
   1548         //Writeback output buffer
   1549         if(LIKELY(!swapzero) )
   1550             acquireFd[count++] = list->outbufAcquireFenceFd;
   1551     }
   1552 
   1553     for(uint32_t i = 0; i < list->numHwLayers; i++) {
   1554         if(((isAbcInUse(ctx)== true ) ||
   1555           (list->hwLayers[i].compositionType == HWC_OVERLAY)) &&
   1556                         list->hwLayers[i].acquireFenceFd >= 0) {
   1557             if(LIKELY(!swapzero) ) {
   1558                 // if ABC is enabled for more than one layer.
   1559                 // renderBufIndexforABC will work as FB.Hence
   1560                 // set the acquireFD from fd - which is coming from copybit
   1561                 if(fd >= 0 && (isAbcInUse(ctx) == true)) {
   1562                     if(ctx->listStats[dpy].renderBufIndexforABC ==(int32_t)i)
   1563                         acquireFd[count++] = fd;
   1564                     else
   1565                         continue;
   1566                 } else
   1567                     acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
   1568             }
   1569         }
   1570         if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
   1571             if(LIKELY(!swapzero) ) {
   1572                 if(fd >= 0) {
   1573                     //set the acquireFD from fd - which is coming from c2d
   1574                     acquireFd[count++] = fd;
   1575                     // Buffer sync IOCTL should be async when using c2d fence is
   1576                     // used
   1577                     data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
   1578                 } else if(list->hwLayers[i].acquireFenceFd >= 0)
   1579                     acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
   1580             }
   1581         }
   1582     }
   1583 
   1584     if ((fd >= 0) && !dpy && ctx->mPtorInfo.isActive()) {
   1585         // Acquire c2d fence of Overlap render buffer
   1586         if(LIKELY(!swapzero) )
   1587             acquireFd[count++] = fd;
   1588     }
   1589 
   1590     data.acq_fen_fd_cnt = count;
   1591     fbFd = ctx->dpyAttr[dpy].fd;
   1592 
   1593     //Waits for acquire fences, returns a release fence
   1594     if(LIKELY(!swapzero)) {
   1595         ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
   1596     }
   1597 
   1598     if(ret < 0) {
   1599         ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed, err=%s",
   1600                   __FUNCTION__, strerror(errno));
   1601         ALOGE("%s: acq_fen_fd_cnt=%d flags=%d fd=%d dpy=%d numHwLayers=%zu",
   1602               __FUNCTION__, data.acq_fen_fd_cnt, data.flags, fbFd,
   1603               dpy, list->numHwLayers);
   1604         close(releaseFd);
   1605         releaseFd = -1;
   1606         close(retireFd);
   1607         retireFd = -1;
   1608     }
   1609 
   1610     for(uint32_t i = 0; i < list->numHwLayers; i++) {
   1611         if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
   1612 #ifdef QCOM_BSP
   1613            list->hwLayers[i].compositionType == HWC_BLIT ||
   1614 #endif
   1615            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
   1616             //Populate releaseFenceFds.
   1617             if(UNLIKELY(swapzero)) {
   1618                 list->hwLayers[i].releaseFenceFd = -1;
   1619             } else if(isExtAnimating) {
   1620                 // Release all the app layer fds immediately,
   1621                 // if animation is in progress.
   1622                 list->hwLayers[i].releaseFenceFd = -1;
   1623             } else if(list->hwLayers[i].releaseFenceFd < 0 ) {
   1624 #ifdef QCOM_BSP
   1625                 //If rotator has not already populated this field
   1626                 // & if it's a not VPU layer
   1627 
   1628                 // if ABC is enabled for more than one layer
   1629                 if(fd >= 0 && (isAbcInUse(ctx) == true) &&
   1630                   ctx->listStats[dpy].renderBufIndexforABC !=(int32_t)i){
   1631                     list->hwLayers[i].releaseFenceFd = dup(fd);
   1632                 } else if((list->hwLayers[i].compositionType == HWC_BLIT)&&
   1633                                                (isAbcInUse(ctx) == false)){
   1634                     //For Blit, the app layers should be released when the Blit
   1635                     //is complete. This fd was passed from copybit->draw
   1636                     list->hwLayers[i].releaseFenceFd = dup(fd);
   1637                 } else
   1638 #endif
   1639                 {
   1640                     list->hwLayers[i].releaseFenceFd = dup(releaseFd);
   1641                 }
   1642             }
   1643         }
   1644     }
   1645 
   1646     if(fd >= 0) {
   1647         close(fd);
   1648         fd = -1;
   1649     }
   1650 
   1651     if (ctx->mCopyBit[dpy]) {
   1652         if (!dpy && ctx->mPtorInfo.isActive())
   1653             ctx->mCopyBit[dpy]->setReleaseFdSync(releaseFd);
   1654         else
   1655             ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
   1656     }
   1657 
   1658     //Signals when MDP finishes reading rotator buffers.
   1659     ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
   1660     close(releaseFd);
   1661     releaseFd = -1;
   1662 
   1663     if(UNLIKELY(swapzero)) {
   1664         list->retireFenceFd = -1;
   1665     } else {
   1666         list->retireFenceFd = retireFd;
   1667     }
   1668     return ret;
   1669 }
   1670 
   1671 void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
   1672         ovutils::eMdpFlags &mdpFlags,
   1673         int rotDownscale, int transform) {
   1674     private_handle_t *hnd = (private_handle_t *)layer->handle;
   1675     MetaData_t *metadata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
   1676 
   1677     if(layer->blending == HWC_BLENDING_PREMULT) {
   1678         ovutils::setMdpFlags(mdpFlags,
   1679                 ovutils::OV_MDP_BLEND_FG_PREMULT);
   1680     }
   1681 
   1682     if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
   1683             metadata->interlaced) {
   1684         ovutils::setMdpFlags(mdpFlags,
   1685                 ovutils::OV_MDP_DEINTERLACE);
   1686     }
   1687 
   1688     // Mark MDP flags with SECURE_OVERLAY_SESSION for driver
   1689     if(isSecureBuffer(hnd)) {
   1690         ovutils::setMdpFlags(mdpFlags,
   1691                 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
   1692         ovutils::setMdpFlags(mdpFlags,
   1693                 ovutils::OV_MDP_SMP_FORCE_ALLOC);
   1694     }
   1695 
   1696     if(isProtectedBuffer(hnd)) {
   1697         ovutils::setMdpFlags(mdpFlags,
   1698                 ovutils::OV_MDP_SMP_FORCE_ALLOC);
   1699     }
   1700 
   1701     if(isSecureDisplayBuffer(hnd)) {
   1702         // Mark MDP flags with SECURE_DISPLAY_OVERLAY_SESSION for driver
   1703         ovutils::setMdpFlags(mdpFlags,
   1704                              ovutils::OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION);
   1705     }
   1706 
   1707     //Pre-rotation will be used using rotator.
   1708     if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
   1709         ovutils::setMdpFlags(mdpFlags,
   1710                 ovutils::OV_MDP_SOURCE_ROTATED_90);
   1711     }
   1712     //No 90 component and no rot-downscale then flips done by MDP
   1713     //If we use rot then it might as well do flips
   1714     if(!(transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
   1715         if(transform & HWC_TRANSFORM_FLIP_H) {
   1716             ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
   1717         }
   1718 
   1719         if(transform & HWC_TRANSFORM_FLIP_V) {
   1720             ovutils::setMdpFlags(mdpFlags,  ovutils::OV_MDP_FLIP_V);
   1721         }
   1722     }
   1723 
   1724     if(metadata &&
   1725         ((metadata->operation & PP_PARAM_HSIC)
   1726         || (metadata->operation & PP_PARAM_IGC)
   1727         || (metadata->operation & PP_PARAM_SHARP2))) {
   1728         ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_PP_EN);
   1729     }
   1730 }
   1731 
   1732 int configRotator(Rotator *rot, Whf& whf,
   1733         hwc_rect_t& crop, const eMdpFlags& mdpFlags,
   1734         const eTransform& orient, const int& downscale) {
   1735 
   1736     // Fix alignments for TILED format
   1737     if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
   1738                             whf.format == MDP_Y_CBCR_H2V2_TILE) {
   1739         whf.w =  utils::alignup(whf.w, 64);
   1740         whf.h = utils::alignup(whf.h, 32);
   1741     }
   1742     rot->setSource(whf);
   1743 
   1744     if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
   1745         qdutils::MDSS_V5) {
   1746          Dim rotCrop(crop.left, crop.top, crop.right - crop.left,
   1747                 crop.bottom - crop.top);
   1748         rot->setCrop(rotCrop);
   1749     }
   1750 
   1751     rot->setFlags(mdpFlags);
   1752     rot->setTransform(orient);
   1753     rot->setDownscale(downscale);
   1754     if(!rot->commit()) return -1;
   1755     return 0;
   1756 }
   1757 
   1758 int configMdp(Overlay *ov, const PipeArgs& parg,
   1759         const eTransform& orient, const hwc_rect_t& crop,
   1760         const hwc_rect_t& pos, const MetaData_t *metadata,
   1761         const eDest& dest) {
   1762     ov->setSource(parg, dest);
   1763     ov->setTransform(orient, dest);
   1764 
   1765     int crop_w = crop.right - crop.left;
   1766     int crop_h = crop.bottom - crop.top;
   1767     Dim dcrop(crop.left, crop.top, crop_w, crop_h);
   1768     ov->setCrop(dcrop, dest);
   1769 
   1770     int posW = pos.right - pos.left;
   1771     int posH = pos.bottom - pos.top;
   1772     Dim position(pos.left, pos.top, posW, posH);
   1773     ov->setPosition(position, dest);
   1774 
   1775     if (metadata)
   1776         ov->setVisualParams(*metadata, dest);
   1777 
   1778     if (!ov->commit(dest)) {
   1779         return -1;
   1780     }
   1781     return 0;
   1782 }
   1783 
   1784 int configColorLayer(hwc_context_t *ctx, hwc_layer_1_t *layer,
   1785         const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
   1786         const eDest& dest) {
   1787 
   1788     hwc_rect_t dst = layer->displayFrame;
   1789     trimLayer(ctx, dpy, 0, dst, dst);
   1790 
   1791     int w = ctx->dpyAttr[dpy].xres;
   1792     int h = ctx->dpyAttr[dpy].yres;
   1793     int dst_w = dst.right - dst.left;
   1794     int dst_h = dst.bottom - dst.top;
   1795     uint32_t color = layer->transform;
   1796     Whf whf(w, h, getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888));
   1797 
   1798     ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SOLID_FILL);
   1799     if (layer->blending == HWC_BLENDING_PREMULT)
   1800         ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_BLEND_FG_PREMULT);
   1801 
   1802     PipeArgs parg(mdpFlags, whf, z, static_cast<eRotFlags>(0),
   1803                   layer->planeAlpha,
   1804                   (ovutils::eBlending) getBlending(layer->blending));
   1805 
   1806     // Configure MDP pipe for Color layer
   1807     Dim pos(dst.left, dst.top, dst_w, dst_h);
   1808     ctx->mOverlay->setSource(parg, dest);
   1809     ctx->mOverlay->setColor(color, dest);
   1810     ctx->mOverlay->setTransform(0, dest);
   1811     ctx->mOverlay->setCrop(pos, dest);
   1812     ctx->mOverlay->setPosition(pos, dest);
   1813 
   1814     if (!ctx->mOverlay->commit(dest)) {
   1815         ALOGE("%s: Configure color layer failed!", __FUNCTION__);
   1816         return -1;
   1817     }
   1818     return 0;
   1819 }
   1820 
   1821 void updateSource(eTransform& orient, Whf& whf,
   1822         hwc_rect_t& crop, Rotator *rot) {
   1823     Dim transformedCrop(crop.left, crop.top,
   1824             crop.right - crop.left,
   1825             crop.bottom - crop.top);
   1826     if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
   1827         qdutils::MDSS_V5) {
   1828         //B-family rotator internally could modify destination dimensions if
   1829         //downscaling is supported
   1830         whf = rot->getDstWhf();
   1831         transformedCrop = rot->getDstDimensions();
   1832     } else {
   1833         //A-family rotator rotates entire buffer irrespective of crop, forcing
   1834         //us to recompute the crop based on transform
   1835         orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
   1836         preRotateSource(orient, whf, transformedCrop);
   1837     }
   1838 
   1839     crop.left = transformedCrop.x;
   1840     crop.top = transformedCrop.y;
   1841     crop.right = transformedCrop.x + transformedCrop.w;
   1842     crop.bottom = transformedCrop.y + transformedCrop.h;
   1843 }
   1844 
   1845 int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer) {
   1846     if(not qdutils::MDPVersion::getInstance().isRotDownscaleEnabled()) {
   1847         return 0;
   1848     }
   1849 
   1850     int downscale = 0;
   1851     hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
   1852     hwc_rect_t dst = layer->displayFrame;
   1853     private_handle_t *hnd = (private_handle_t *)layer->handle;
   1854 
   1855     if(not hnd) {
   1856         return 0;
   1857     }
   1858 
   1859     MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
   1860     bool isInterlaced = metadata && (metadata->operation & PP_PARAM_INTERLACED)
   1861                 && metadata->interlaced;
   1862     int transform = layer->transform;
   1863     uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
   1864 
   1865     if(isYuvBuffer(hnd)) {
   1866         if(ctx->mMDP.version >= qdutils::MDP_V4_2 &&
   1867                 ctx->mMDP.version < qdutils::MDSS_V5) {
   1868             downscale = Rotator::getDownscaleFactor(crop.right - crop.left,
   1869                     crop.bottom - crop.top, dst.right - dst.left,
   1870                     dst.bottom - dst.top, format, isInterlaced);
   1871         } else {
   1872             Dim adjCrop(crop.left, crop.top, crop.right - crop.left,
   1873                     crop.bottom - crop.top);
   1874             Dim pos(dst.left, dst.top, dst.right - dst.left,
   1875                     dst.bottom - dst.top);
   1876             if(transform & HAL_TRANSFORM_ROT_90) {
   1877                 swap(adjCrop.w, adjCrop.h);
   1878             }
   1879             downscale = Rotator::getDownscaleFactor(adjCrop.w, adjCrop.h, pos.w,
   1880                     pos.h, format, isInterlaced);
   1881         }
   1882     }
   1883     return downscale;
   1884 }
   1885 
   1886 bool isZoomModeEnabled(hwc_rect_t crop) {
   1887     // This does not work for zooming in top left corner of the image
   1888     return(crop.top > 0 || crop.left > 0);
   1889 }
   1890 
   1891 void updateCropAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& crop, int dpy) {
   1892     ALOGD_IF(HWC_UTILS_DEBUG, "dpy %d Source crop [%d %d %d %d]", dpy,
   1893              crop.left, crop.top, crop.right, crop.bottom);
   1894     if(isZoomModeEnabled(crop)) {
   1895         Dim srcCrop(crop.left, crop.top,
   1896                 crop.right - crop.left,
   1897                 crop.bottom - crop.top);
   1898         int extW = ctx->dpyAttr[dpy].xres;
   1899         int extH = ctx->dpyAttr[dpy].yres;
   1900         //Crop the original video in order to fit external display aspect ratio
   1901         if(srcCrop.w * extH < extW * srcCrop.h) {
   1902             int offset = (srcCrop.h - ((srcCrop.w * extH) / extW)) / 2;
   1903             crop.top += offset;
   1904             crop.bottom -= offset;
   1905         } else {
   1906             int offset = (srcCrop.w - ((extW * srcCrop.h) / extH)) / 2;
   1907             crop.left += offset;
   1908             crop.right -= offset;
   1909         }
   1910         ALOGD_IF(HWC_UTILS_DEBUG, "External Resolution [%d %d] dpy %d Modified"
   1911                  " source crop [%d %d %d %d]", extW, extH, dpy,
   1912                  crop.left, crop.top, crop.right, crop.bottom);
   1913     }
   1914 }
   1915 
   1916 void updateDestAIVVideoMode(hwc_context_t *ctx, hwc_rect_t crop,
   1917                            hwc_rect_t& dst, int dpy) {
   1918     ALOGD_IF(HWC_UTILS_DEBUG, "dpy %d Destination position [%d %d %d %d]", dpy,
   1919              dst.left, dst.top, dst.right, dst.bottom);
   1920     Dim srcCrop(crop.left, crop.top,
   1921             crop.right - crop.left,
   1922             crop.bottom - crop.top);
   1923     int extW = ctx->dpyAttr[dpy].xres;
   1924     int extH = ctx->dpyAttr[dpy].yres;
   1925     // Set the destination coordinates of external display to full screen,
   1926     // when zoom in mode is enabled or the ratio between video aspect ratio
   1927     // and external display aspect ratio is below the minimum tolerance level
   1928     // and above maximum tolerance level
   1929     float videoAspectRatio = ((float)srcCrop.w / (float)srcCrop.h);
   1930     float extDisplayAspectRatio = ((float)extW / (float)extH);
   1931     float videoToExternalRatio = videoAspectRatio / extDisplayAspectRatio;
   1932     if((fabs(1.0f - videoToExternalRatio) <= ctx->mAspectRatioToleranceLevel) ||
   1933         (isZoomModeEnabled(crop))) {
   1934         dst.left = 0;
   1935         dst.top = 0;
   1936         dst.right = extW;
   1937         dst.bottom = extH;
   1938     }
   1939     ALOGD_IF(HWC_UTILS_DEBUG, "External Resolution [%d %d] dpy %d Modified"
   1940              " Destination position [%d %d %d %d] Source crop [%d %d %d %d]",
   1941              extW, extH, dpy, dst.left, dst.top, dst.right, dst.bottom,
   1942              crop.left, crop.top, crop.right, crop.bottom);
   1943 }
   1944 
   1945 void updateCoordinates(hwc_context_t *ctx, hwc_rect_t& crop,
   1946                            hwc_rect_t& dst, int dpy) {
   1947     updateCropAIVVideoMode(ctx, crop, dpy);
   1948     updateDestAIVVideoMode(ctx, crop, dst, dpy);
   1949 }
   1950 
   1951 int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
   1952         const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
   1953         const eDest& dest, Rotator **rot) {
   1954 
   1955     private_handle_t *hnd = (private_handle_t *)layer->handle;
   1956 
   1957     if(!hnd) {
   1958         if (layer->flags & HWC_COLOR_FILL) {
   1959             // Configure Color layer
   1960             return configColorLayer(ctx, layer, dpy, mdpFlags, z, dest);
   1961         }
   1962         ALOGE("%s: layer handle is NULL", __FUNCTION__);
   1963         return -1;
   1964     }
   1965 
   1966     MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
   1967 
   1968     hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
   1969     hwc_rect_t dst = layer->displayFrame;
   1970     int transform = layer->transform;
   1971     eTransform orient = static_cast<eTransform>(transform);
   1972     int rotFlags = ovutils::ROT_FLAGS_NONE;
   1973     uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
   1974     Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
   1975 
   1976     // Handle R/B swap
   1977     if (layer->flags & HWC_FORMAT_RB_SWAP) {
   1978         if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
   1979             whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
   1980         else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
   1981             whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
   1982     }
   1983     // update source crop and destination position of AIV video layer.
   1984     if(ctx->listStats[dpy].mAIVVideoMode && isYuvBuffer(hnd)) {
   1985         updateCoordinates(ctx, crop, dst, dpy);
   1986     }
   1987     calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
   1988     int downscale = getRotDownscale(ctx, layer);
   1989     setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
   1990 
   1991     //if 90 component or downscale, use rot
   1992     if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
   1993         *rot = ctx->mRotMgr->getNext();
   1994         if(*rot == NULL) return -1;
   1995         ctx->mLayerRotMap[dpy]->add(layer, *rot);
   1996         BwcPM::setBwc(ctx, dpy, hnd, crop, dst, transform, downscale,
   1997                 mdpFlags);
   1998         //Configure rotator for pre-rotation
   1999         if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
   2000             ALOGE("%s: configRotator failed!", __FUNCTION__);
   2001             return -1;
   2002         }
   2003         updateSource(orient, whf, crop, *rot);
   2004         rotFlags |= ROT_PREROTATED;
   2005     }
   2006 
   2007     //For the mdp, since either we are pre-rotating or MDP does flips
   2008     orient = OVERLAY_TRANSFORM_0;
   2009     transform = 0;
   2010     PipeArgs parg(mdpFlags, whf, z,
   2011                   static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
   2012                   (ovutils::eBlending) getBlending(layer->blending));
   2013 
   2014     if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
   2015         ALOGE("%s: commit failed for low res panel", __FUNCTION__);
   2016         return -1;
   2017     }
   2018     return 0;
   2019 }
   2020 
   2021 //Helper to 1) Ensure crops dont have gaps 2) Ensure L and W are even
   2022 void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,
   2023         private_handle_t *hnd) {
   2024     if(cropL.right - cropL.left) {
   2025         if(isYuvBuffer(hnd)) {
   2026             //Always safe to even down left
   2027             ovutils::even_floor(cropL.left);
   2028             //If right is even, automatically width is even, since left is
   2029             //already even
   2030             ovutils::even_floor(cropL.right);
   2031         }
   2032         //Make sure there are no gaps between left and right splits if the layer
   2033         //is spread across BOTH halves
   2034         if(cropR.right - cropR.left) {
   2035             cropR.left = cropL.right;
   2036         }
   2037     }
   2038 
   2039     if(cropR.right - cropR.left) {
   2040         if(isYuvBuffer(hnd)) {
   2041             //Always safe to even down left
   2042             ovutils::even_floor(cropR.left);
   2043             //If right is even, automatically width is even, since left is
   2044             //already even
   2045             ovutils::even_floor(cropR.right);
   2046         }
   2047     }
   2048 }
   2049 
   2050 int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
   2051         const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
   2052         const eDest& lDest, const eDest& rDest,
   2053         Rotator **rot) {
   2054     private_handle_t *hnd = (private_handle_t *)layer->handle;
   2055     if(!hnd) {
   2056         ALOGE("%s: layer handle is NULL", __FUNCTION__);
   2057         return -1;
   2058     }
   2059 
   2060     MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
   2061 
   2062     int hw_w = ctx->dpyAttr[dpy].xres;
   2063     int hw_h = ctx->dpyAttr[dpy].yres;
   2064     hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
   2065     hwc_rect_t dst = layer->displayFrame;
   2066     int transform = layer->transform;
   2067     eTransform orient = static_cast<eTransform>(transform);
   2068     int rotFlags = ROT_FLAGS_NONE;
   2069     uint32_t format = ovutils::getMdpFormat(hnd->format, hnd->flags);
   2070     Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
   2071 
   2072     // Handle R/B swap
   2073     if (layer->flags & HWC_FORMAT_RB_SWAP) {
   2074         if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
   2075             whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
   2076         else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
   2077             whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
   2078     }
   2079 
   2080     // update source crop and destination position of AIV video layer.
   2081     if(ctx->listStats[dpy].mAIVVideoMode && isYuvBuffer(hnd)) {
   2082         updateCoordinates(ctx, crop, dst, dpy);
   2083     }
   2084 
   2085     /* Calculate the external display position based on MDP downscale,
   2086        ActionSafe, and extorientation features. */
   2087     calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
   2088     int downscale = getRotDownscale(ctx, layer);
   2089     setMdpFlags(ctx, layer, mdpFlagsL, downscale, transform);
   2090 
   2091     if(lDest != OV_INVALID && rDest != OV_INVALID) {
   2092         //Enable overfetch
   2093         setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
   2094     }
   2095 
   2096     //Will do something only if feature enabled and conditions suitable
   2097     //hollow call otherwise
   2098     if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
   2099         overlay::Writeback *wb = overlay::Writeback::getInstance();
   2100         whf.format = wb->getOutputFormat();
   2101     }
   2102 
   2103     if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
   2104         (*rot) = ctx->mRotMgr->getNext();
   2105         if((*rot) == NULL) return -1;
   2106         ctx->mLayerRotMap[dpy]->add(layer, *rot);
   2107         //Configure rotator for pre-rotation
   2108         if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
   2109             ALOGE("%s: configRotator failed!", __FUNCTION__);
   2110             return -1;
   2111         }
   2112         updateSource(orient, whf, crop, *rot);
   2113         rotFlags |= ROT_PREROTATED;
   2114     }
   2115 
   2116     eMdpFlags mdpFlagsR = mdpFlagsL;
   2117     setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER);
   2118 
   2119     hwc_rect_t tmp_cropL = {0}, tmp_dstL = {0};
   2120     hwc_rect_t tmp_cropR = {0}, tmp_dstR = {0};
   2121 
   2122     const int lSplit = getLeftSplit(ctx, dpy);
   2123 
   2124     // Calculate Left rects
   2125     if(dst.left < lSplit) {
   2126         tmp_cropL = crop;
   2127         tmp_dstL = dst;
   2128         hwc_rect_t scissor = {0, 0, lSplit, hw_h };
   2129         scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
   2130         qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
   2131     }
   2132 
   2133     // Calculate Right rects
   2134     if(dst.right > lSplit) {
   2135         tmp_cropR = crop;
   2136         tmp_dstR = dst;
   2137         hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
   2138         scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
   2139         qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
   2140     }
   2141 
   2142     sanitizeSourceCrop(tmp_cropL, tmp_cropR, hnd);
   2143 
   2144     //When buffer is H-flipped, contents of mixer config also needs to swapped
   2145     //Not needed if the layer is confined to one half of the screen.
   2146     //If rotator has been used then it has also done the flips, so ignore them.
   2147     if((orient & OVERLAY_TRANSFORM_FLIP_H) && (dst.left < lSplit) &&
   2148             (dst.right > lSplit) && (*rot) == NULL) {
   2149         hwc_rect_t new_cropR;
   2150         new_cropR.left = tmp_cropL.left;
   2151         new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
   2152 
   2153         hwc_rect_t new_cropL;
   2154         new_cropL.left  = new_cropR.right;
   2155         new_cropL.right = tmp_cropR.right;
   2156 
   2157         tmp_cropL.left =  new_cropL.left;
   2158         tmp_cropL.right =  new_cropL.right;
   2159 
   2160         tmp_cropR.left = new_cropR.left;
   2161         tmp_cropR.right =  new_cropR.right;
   2162 
   2163     }
   2164 
   2165     //For the mdp, since either we are pre-rotating or MDP does flips
   2166     orient = OVERLAY_TRANSFORM_0;
   2167     transform = 0;
   2168 
   2169     //configure left mixer
   2170     if(lDest != OV_INVALID) {
   2171         PipeArgs pargL(mdpFlagsL, whf, z,
   2172                        static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
   2173                        (ovutils::eBlending) getBlending(layer->blending));
   2174 
   2175         if(configMdp(ctx->mOverlay, pargL, orient,
   2176                 tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
   2177             ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
   2178             return -1;
   2179         }
   2180     }
   2181 
   2182     //configure right mixer
   2183     if(rDest != OV_INVALID) {
   2184         PipeArgs pargR(mdpFlagsR, whf, z,
   2185                        static_cast<eRotFlags>(rotFlags),
   2186                        layer->planeAlpha,
   2187                        (ovutils::eBlending) getBlending(layer->blending));
   2188         tmp_dstR.right = tmp_dstR.right - lSplit;
   2189         tmp_dstR.left = tmp_dstR.left - lSplit;
   2190         if(configMdp(ctx->mOverlay, pargR, orient,
   2191                 tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
   2192             ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
   2193             return -1;
   2194         }
   2195     }
   2196 
   2197     return 0;
   2198 }
   2199 
   2200 int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
   2201         const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
   2202         const eDest& lDest, const eDest& rDest,
   2203         Rotator **rot) {
   2204     private_handle_t *hnd = (private_handle_t *)layer->handle;
   2205     if(!hnd) {
   2206         ALOGE("%s: layer handle is NULL", __FUNCTION__);
   2207         return -1;
   2208     }
   2209 
   2210     MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
   2211 
   2212     hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);;
   2213     hwc_rect_t dst = layer->displayFrame;
   2214     int transform = layer->transform;
   2215     eTransform orient = static_cast<eTransform>(transform);
   2216     const int downscale = 0;
   2217     int rotFlags = ROT_FLAGS_NONE;
   2218     //Splitting only YUV layer on primary panel needs different zorders
   2219     //for both layers as both the layers are configured to single mixer
   2220     eZorder lz = z;
   2221     eZorder rz = (eZorder)(z + 1);
   2222 
   2223     Whf whf(getWidth(hnd), getHeight(hnd),
   2224             getMdpFormat(hnd->format), (uint32_t)hnd->size);
   2225 
   2226     // update source crop and destination position of AIV video layer.
   2227     if(ctx->listStats[dpy].mAIVVideoMode && isYuvBuffer(hnd)) {
   2228         updateCoordinates(ctx, crop, dst, dpy);
   2229     }
   2230 
   2231     /* Calculate the external display position based on MDP downscale,
   2232        ActionSafe, and extorientation features. */
   2233     calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
   2234 
   2235     setMdpFlags(ctx, layer, mdpFlagsL, 0, transform);
   2236     trimLayer(ctx, dpy, transform, crop, dst);
   2237 
   2238     if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
   2239         (*rot) = ctx->mRotMgr->getNext();
   2240         if((*rot) == NULL) return -1;
   2241         ctx->mLayerRotMap[dpy]->add(layer, *rot);
   2242         //Configure rotator for pre-rotation
   2243         if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
   2244             ALOGE("%s: configRotator failed!", __FUNCTION__);
   2245             return -1;
   2246         }
   2247         updateSource(orient, whf, crop, *rot);
   2248         rotFlags |= ROT_PREROTATED;
   2249     }
   2250 
   2251     eMdpFlags mdpFlagsR = mdpFlagsL;
   2252     int lSplit = dst.left + (dst.right - dst.left)/2;
   2253 
   2254     hwc_rect_t tmp_cropL = {0}, tmp_dstL = {0};
   2255     hwc_rect_t tmp_cropR = {0}, tmp_dstR = {0};
   2256 
   2257     if(lDest != OV_INVALID) {
   2258         tmp_cropL = crop;
   2259         tmp_dstL = dst;
   2260         hwc_rect_t scissor = {dst.left, dst.top, lSplit, dst.bottom };
   2261         qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
   2262     }
   2263     if(rDest != OV_INVALID) {
   2264         tmp_cropR = crop;
   2265         tmp_dstR = dst;
   2266         hwc_rect_t scissor = {lSplit, dst.top, dst.right, dst.bottom };
   2267         qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
   2268     }
   2269 
   2270     sanitizeSourceCrop(tmp_cropL, tmp_cropR, hnd);
   2271 
   2272     //When buffer is H-flipped, contents of mixer config also needs to swapped
   2273     //Not needed if the layer is confined to one half of the screen.
   2274     //If rotator has been used then it has also done the flips, so ignore them.
   2275     if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
   2276             && rDest != OV_INVALID && (*rot) == NULL) {
   2277         hwc_rect_t new_cropR;
   2278         new_cropR.left = tmp_cropL.left;
   2279         new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
   2280 
   2281         hwc_rect_t new_cropL;
   2282         new_cropL.left  = new_cropR.right;
   2283         new_cropL.right = tmp_cropR.right;
   2284 
   2285         tmp_cropL.left =  new_cropL.left;
   2286         tmp_cropL.right =  new_cropL.right;
   2287 
   2288         tmp_cropR.left = new_cropR.left;
   2289         tmp_cropR.right =  new_cropR.right;
   2290 
   2291     }
   2292 
   2293     //For the mdp, since either we are pre-rotating or MDP does flips
   2294     orient = OVERLAY_TRANSFORM_0;
   2295     transform = 0;
   2296 
   2297     //configure left half
   2298     if(lDest != OV_INVALID) {
   2299         PipeArgs pargL(mdpFlagsL, whf, lz,
   2300                 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
   2301                 (ovutils::eBlending) getBlending(layer->blending));
   2302 
   2303         if(configMdp(ctx->mOverlay, pargL, orient,
   2304                     tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
   2305             ALOGE("%s: commit failed for left half config", __FUNCTION__);
   2306             return -1;
   2307         }
   2308     }
   2309 
   2310     //configure right half
   2311     if(rDest != OV_INVALID) {
   2312         PipeArgs pargR(mdpFlagsR, whf, rz,
   2313                 static_cast<eRotFlags>(rotFlags),
   2314                 layer->planeAlpha,
   2315                 (ovutils::eBlending) getBlending(layer->blending));
   2316         if(configMdp(ctx->mOverlay, pargR, orient,
   2317                     tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
   2318             ALOGE("%s: commit failed for right half config", __FUNCTION__);
   2319             return -1;
   2320         }
   2321     }
   2322 
   2323     return 0;
   2324 }
   2325 
   2326 bool canUseRotator(hwc_context_t *ctx, int dpy) {
   2327     if(ctx->mOverlay->isDMAMultiplexingSupported() &&
   2328             isSecondaryConnected(ctx) &&
   2329             !ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) {
   2330         /* mdss driver on certain targets support multiplexing of DMA pipe
   2331          * in LINE and BLOCK modes for writeback panels.
   2332          */
   2333         if(dpy == HWC_DISPLAY_PRIMARY)
   2334             return false;
   2335     }
   2336     if((ctx->mMDP.version == qdutils::MDP_V3_0_4)
   2337           ||(ctx->mMDP.version == qdutils::MDP_V3_0_5))
   2338         return false;
   2339     return true;
   2340 }
   2341 
   2342 int getLeftSplit(hwc_context_t *ctx, const int& dpy) {
   2343     //Default even split for all displays with high res
   2344     int lSplit = ctx->dpyAttr[dpy].xres / 2;
   2345     if(dpy == HWC_DISPLAY_PRIMARY &&
   2346             qdutils::MDPVersion::getInstance().getLeftSplit()) {
   2347         //Override if split published by driver for primary
   2348         lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
   2349     }
   2350     return lSplit;
   2351 }
   2352 
   2353 bool isDisplaySplit(hwc_context_t* ctx, int dpy) {
   2354     qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
   2355     if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxPipeWidth()) {
   2356         return true;
   2357     }
   2358     //For testing we could split primary via device tree values
   2359     if(dpy == HWC_DISPLAY_PRIMARY && mdpHw.getRightSplit()) {
   2360         return true;
   2361     }
   2362     return false;
   2363 }
   2364 
   2365 //clear prev layer prop flags and realloc for current frame
   2366 void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers) {
   2367     if(ctx->layerProp[dpy]) {
   2368        delete[] ctx->layerProp[dpy];
   2369        ctx->layerProp[dpy] = NULL;
   2370     }
   2371     ctx->layerProp[dpy] = new LayerProp[numAppLayers];
   2372 }
   2373 
   2374 bool isAbcInUse(hwc_context_t *ctx){
   2375   return (ctx->enableABC && ctx->listStats[0].renderBufIndexforABC == 0);
   2376 }
   2377 
   2378 void dumpBuffer(private_handle_t *ohnd, char *bufferName) {
   2379     if (ohnd != NULL && ohnd->base) {
   2380         char dumpFilename[PATH_MAX];
   2381         bool bResult = false;
   2382         int width = getWidth(ohnd);
   2383         int height = getHeight(ohnd);
   2384         int format = ohnd->format;
   2385         //dummy aligned w & h.
   2386         int alW = 0, alH = 0;
   2387         int size = getBufferSizeAndDimensions(width, height, format, alW, alH);
   2388         snprintf(dumpFilename, sizeof(dumpFilename), "/data/%s.%s.%dx%d.raw",
   2389             bufferName,
   2390             overlay::utils::getFormatString(utils::getMdpFormat(format)),
   2391             width, height);
   2392         FILE* fp = fopen(dumpFilename, "w+");
   2393         if (NULL != fp) {
   2394             bResult = (bool) fwrite((void*)ohnd->base, size, 1, fp);
   2395             fclose(fp);
   2396         }
   2397         ALOGD("Buffer[%s] Dump to %s: %s",
   2398         bufferName, dumpFilename, bResult ? "Success" : "Fail");
   2399     }
   2400 }
   2401 
   2402 bool isGLESComp(hwc_context_t *ctx,
   2403                      hwc_display_contents_1_t* list) {
   2404     int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
   2405     for(int index = 0; index < numAppLayers; index++) {
   2406         hwc_layer_1_t* layer = &(list->hwLayers[index]);
   2407         if(layer->compositionType == HWC_FRAMEBUFFER)
   2408             return true;
   2409     }
   2410     return false;
   2411 }
   2412 
   2413 void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
   2414     struct gpu_hint_info *gpuHint = &ctx->mGPUHintInfo;
   2415     if(!gpuHint->mGpuPerfModeEnable || !ctx || !list)
   2416         return;
   2417 
   2418 #ifdef QCOM_BSP
   2419     /* Set the GPU hint flag to high for MIXED/GPU composition only for
   2420        first frame after MDP -> GPU/MIXED mode transition. Set the GPU
   2421        hint to default if the previous composition is GPU or current GPU
   2422        composition is due to idle fallback */
   2423     if(!gpuHint->mEGLDisplay || !gpuHint->mEGLContext) {
   2424         gpuHint->mEGLDisplay = eglGetCurrentDisplay();
   2425         if(!gpuHint->mEGLDisplay) {
   2426             ALOGW("%s Warning: EGL current display is NULL", __FUNCTION__);
   2427             return;
   2428         }
   2429         gpuHint->mEGLContext = eglGetCurrentContext();
   2430         if(!gpuHint->mEGLContext) {
   2431             ALOGW("%s Warning: EGL current context is NULL", __FUNCTION__);
   2432             return;
   2433         }
   2434     }
   2435     if(isGLESComp(ctx, list)) {
   2436         if(gpuHint->mCompositionState != COMPOSITION_STATE_GPU
   2437             && !MDPComp::isIdleFallback()) {
   2438             EGLint attr_list[] = {EGL_GPU_HINT_1,
   2439                                   EGL_GPU_LEVEL_3,
   2440                                   EGL_NONE };
   2441             if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_3) &&
   2442                 !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
   2443                                     gpuHint->mEGLContext, attr_list)) {
   2444                 ALOGW("eglGpuPerfHintQCOM failed for Built in display");
   2445             } else {
   2446                 gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_3;
   2447                 gpuHint->mCompositionState = COMPOSITION_STATE_GPU;
   2448             }
   2449         } else {
   2450             EGLint attr_list[] = {EGL_GPU_HINT_1,
   2451                                   EGL_GPU_LEVEL_0,
   2452                                   EGL_NONE };
   2453             if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
   2454                 !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
   2455                                     gpuHint->mEGLContext, attr_list)) {
   2456                 ALOGW("eglGpuPerfHintQCOM failed for Built in display");
   2457             } else {
   2458                 gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
   2459             }
   2460             if(MDPComp::isIdleFallback()) {
   2461                 gpuHint->mCompositionState = COMPOSITION_STATE_IDLE_FALLBACK;
   2462             }
   2463         }
   2464     } else {
   2465         /* set the GPU hint flag to default for MDP composition */
   2466         EGLint attr_list[] = {EGL_GPU_HINT_1,
   2467                               EGL_GPU_LEVEL_0,
   2468                               EGL_NONE };
   2469         if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
   2470                 !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
   2471                                     gpuHint->mEGLContext, attr_list)) {
   2472             ALOGW("eglGpuPerfHintQCOM failed for Built in display");
   2473         } else {
   2474             gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
   2475         }
   2476         gpuHint->mCompositionState = COMPOSITION_STATE_MDP;
   2477     }
   2478 #endif
   2479 }
   2480 
   2481 bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
   2482     // To be peripheral, 3 boundaries should match.
   2483     uint8_t eqBounds = 0;
   2484     if (rect1.left == rect2.left)
   2485         eqBounds++;
   2486     if (rect1.top == rect2.top)
   2487         eqBounds++;
   2488     if (rect1.right == rect2.right)
   2489         eqBounds++;
   2490     if (rect1.bottom == rect2.bottom)
   2491         eqBounds++;
   2492     return (eqBounds == 3);
   2493 }
   2494 
   2495 void BwcPM::setBwc(const hwc_context_t *ctx, const int& dpy,
   2496         const private_handle_t *hnd,
   2497         const hwc_rect_t& crop, const hwc_rect_t& dst,
   2498         const int& transform,const int& downscale,
   2499         ovutils::eMdpFlags& mdpFlags) {
   2500     //Target doesnt support Bwc
   2501     qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
   2502     if(not mdpHw.supportsBWC()) {
   2503         return;
   2504     }
   2505     //Disabled at runtime
   2506     if(not ctx->mBWCEnabled) return;
   2507     //BWC not supported with rot-downscale
   2508     if(downscale) return;
   2509     //Not enabled for secondary displays
   2510     if(dpy) return;
   2511     //Not enabled for non-video buffers
   2512     if(not isYuvBuffer(hnd)) return;
   2513 
   2514     int src_w = crop.right - crop.left;
   2515     int src_h = crop.bottom - crop.top;
   2516     int dst_w = dst.right - dst.left;
   2517     int dst_h = dst.bottom - dst.top;
   2518     if(transform & HAL_TRANSFORM_ROT_90) {
   2519         swap(src_w, src_h);
   2520     }
   2521     //src width > MAX mixer supported dim
   2522     if(src_w > (int) qdutils::MDPVersion::getInstance().getMaxPipeWidth()) {
   2523         return;
   2524     }
   2525     //Decimation necessary, cannot use BWC. H/W requirement.
   2526     if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
   2527         uint8_t horzDeci = 0;
   2528         uint8_t vertDeci = 0;
   2529         ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horzDeci,
   2530                 vertDeci);
   2531         if(horzDeci || vertDeci) return;
   2532     }
   2533 
   2534     ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDSS_MDP_BWC_EN);
   2535 }
   2536 
   2537 void LayerRotMap::add(hwc_layer_1_t* layer, Rotator *rot) {
   2538     if(mCount >= RotMgr::MAX_ROT_SESS) return;
   2539     mLayer[mCount] = layer;
   2540     mRot[mCount] = rot;
   2541     mCount++;
   2542 }
   2543 
   2544 void LayerRotMap::reset() {
   2545     for (int i = 0; i < RotMgr::MAX_ROT_SESS; i++) {
   2546         mLayer[i] = 0;
   2547         mRot[i] = 0;
   2548     }
   2549     mCount = 0;
   2550 }
   2551 
   2552 void LayerRotMap::clear() {
   2553     RotMgr::getInstance()->markUnusedTop(mCount);
   2554     reset();
   2555 }
   2556 
   2557 bool LayerRotMap::isRotCached(uint32_t index) const {
   2558     overlay::Rotator* rot = getRot(index);
   2559     hwc_layer_1_t* layer =  getLayer(index);
   2560 
   2561     if(rot and layer and layer->handle) {
   2562         private_handle_t *hnd = (private_handle_t *)(layer->handle);
   2563         return (rot->isRotCached(hnd->fd,(uint32_t)(hnd->offset)));
   2564     }
   2565     return false;
   2566 }
   2567 
   2568 void LayerRotMap::setReleaseFd(const int& fence) {
   2569     for(uint32_t i = 0; i < mCount; i++) {
   2570         if(mRot[i] and mLayer[i] and mLayer[i]->handle) {
   2571             /* Ensure that none of the above (Rotator-instance,
   2572              * layer and layer-handle) are NULL*/
   2573             if(isRotCached(i))
   2574                 mRot[i]->setPrevBufReleaseFd(dup(fence));
   2575             else
   2576                 mRot[i]->setCurrBufReleaseFd(dup(fence));
   2577         }
   2578     }
   2579 }
   2580 
   2581 void resetROI(hwc_context_t *ctx, const int dpy) {
   2582     const int fbXRes = (int)ctx->dpyAttr[dpy].xres;
   2583     const int fbYRes = (int)ctx->dpyAttr[dpy].yres;
   2584     if(isDisplaySplit(ctx, dpy)) {
   2585         const int lSplit = getLeftSplit(ctx, dpy);
   2586         ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0, lSplit, fbYRes};
   2587         ctx->listStats[dpy].rRoi = (struct hwc_rect){lSplit, 0, fbXRes, fbYRes};
   2588     } else  {
   2589         ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0,fbXRes, fbYRes};
   2590         ctx->listStats[dpy].rRoi = (struct hwc_rect){0, 0, 0, 0};
   2591     }
   2592 }
   2593 
   2594 hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary)
   2595 {
   2596    if(!isValidRect(roi))
   2597       return roi;
   2598 
   2599    struct hwc_rect t_roi = roi;
   2600 
   2601    const int LEFT_ALIGN = qdutils::MDPVersion::getInstance().getLeftAlign();
   2602    const int WIDTH_ALIGN = qdutils::MDPVersion::getInstance().getWidthAlign();
   2603    const int TOP_ALIGN = qdutils::MDPVersion::getInstance().getTopAlign();
   2604    const int HEIGHT_ALIGN = qdutils::MDPVersion::getInstance().getHeightAlign();
   2605    const int MIN_WIDTH = qdutils::MDPVersion::getInstance().getMinROIWidth();
   2606    const int MIN_HEIGHT = qdutils::MDPVersion::getInstance().getMinROIHeight();
   2607 
   2608    /* Align to minimum width recommended by the panel */
   2609    if((t_roi.right - t_roi.left) < MIN_WIDTH) {
   2610        if((t_roi.left + MIN_WIDTH) > boundary.right)
   2611            t_roi.left = t_roi.right - MIN_WIDTH;
   2612        else
   2613            t_roi.right = t_roi.left + MIN_WIDTH;
   2614    }
   2615 
   2616   /* Align to minimum height recommended by the panel */
   2617    if((t_roi.bottom - t_roi.top) < MIN_HEIGHT) {
   2618        if((t_roi.top + MIN_HEIGHT) > boundary.bottom)
   2619            t_roi.top = t_roi.bottom - MIN_HEIGHT;
   2620        else
   2621            t_roi.bottom = t_roi.top + MIN_HEIGHT;
   2622    }
   2623 
   2624    /* Align left and width to meet panel restrictions */
   2625    if(LEFT_ALIGN)
   2626        t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
   2627 
   2628    if(WIDTH_ALIGN) {
   2629        int width = t_roi.right - t_roi.left;
   2630        width = WIDTH_ALIGN * ((width + (WIDTH_ALIGN - 1)) / WIDTH_ALIGN);
   2631        t_roi.right = t_roi.left + width;
   2632 
   2633        if(t_roi.right > boundary.right) {
   2634            t_roi.right = boundary.right;
   2635            t_roi.left = t_roi.right - width;
   2636 
   2637            if(LEFT_ALIGN)
   2638                t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
   2639        }
   2640    }
   2641 
   2642 
   2643    /* Align top and height to meet panel restrictions */
   2644    if(TOP_ALIGN)
   2645        t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
   2646 
   2647    if(HEIGHT_ALIGN) {
   2648        int height = t_roi.bottom - t_roi.top;
   2649        height = HEIGHT_ALIGN *  ((height + (HEIGHT_ALIGN - 1)) / HEIGHT_ALIGN);
   2650        t_roi.bottom = t_roi.top  + height;
   2651 
   2652        if(t_roi.bottom > boundary.bottom) {
   2653            t_roi.bottom = boundary.bottom;
   2654            t_roi.top = t_roi.bottom - height;
   2655 
   2656            if(TOP_ALIGN)
   2657                t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
   2658        }
   2659    }
   2660 
   2661 
   2662    return t_roi;
   2663 }
   2664 
   2665 void handle_pause(hwc_context_t* ctx, int dpy) {
   2666     if(ctx->dpyAttr[dpy].connected) {
   2667         ctx->mDrawLock.lock();
   2668         ctx->dpyAttr[dpy].isActive = true;
   2669         ctx->dpyAttr[dpy].isPause = true;
   2670         ctx->mDrawLock.unlock();
   2671         ctx->proc->invalidate(ctx->proc);
   2672 
   2673         usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
   2674                * 2 / 1000);
   2675 
   2676         // At this point all the pipes used by External have been
   2677         // marked as UNSET.
   2678         ctx->mDrawLock.lock();
   2679         // Perform commit to unstage the pipes.
   2680         if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
   2681             ALOGE("%s: display commit fail! for %d dpy",
   2682                   __FUNCTION__, dpy);
   2683         }
   2684         ctx->mDrawLock.unlock();
   2685         ctx->proc->invalidate(ctx->proc);
   2686     }
   2687     return;
   2688 }
   2689 
   2690 void handle_resume(hwc_context_t* ctx, int dpy) {
   2691     if(ctx->dpyAttr[dpy].connected) {
   2692         ctx->mDrawLock.lock();
   2693         ctx->dpyAttr[dpy].isConfiguring = true;
   2694         ctx->dpyAttr[dpy].isActive = true;
   2695         ctx->mDrawLock.unlock();
   2696         ctx->proc->invalidate(ctx->proc);
   2697 
   2698         usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
   2699                * 2 / 1000);
   2700 
   2701         //At this point external has all the pipes it would need.
   2702         ctx->mDrawLock.lock();
   2703         ctx->dpyAttr[dpy].isPause = false;
   2704         ctx->mDrawLock.unlock();
   2705         ctx->proc->invalidate(ctx->proc);
   2706     }
   2707     return;
   2708 }
   2709 
   2710 void clearPipeResources(hwc_context_t* ctx, int dpy) {
   2711     if(ctx->mOverlay) {
   2712         ctx->mOverlay->configBegin();
   2713         ctx->mOverlay->configDone();
   2714     }
   2715     if(ctx->mRotMgr) {
   2716         ctx->mRotMgr->clear();
   2717     }
   2718     // Call a display commit to ensure that pipes and associated
   2719     // fd's are cleaned up.
   2720     if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
   2721         ALOGE("%s: display commit failed for  %d", __FUNCTION__, dpy);
   2722     }
   2723 }
   2724 
   2725 // Handles online events when HDMI is the primary display. In particular,
   2726 // online events for hdmi connected before AND after boot up and HWC init.
   2727 void handle_online(hwc_context_t* ctx, int dpy) {
   2728     //On 8994 due to hardware limitations, we disable bwc completely when HDMI
   2729     //intf is active
   2730     if(qdutils::MDPVersion::getInstance().is8994() and
   2731             qdutils::MDPVersion::getInstance().supportsBWC()) {
   2732         ctx->mBWCEnabled = false;
   2733     }
   2734     // Close the current fd if it was opened earlier on when HWC
   2735     // was initialized.
   2736     if (ctx->dpyAttr[dpy].fd >= 0) {
   2737         close(ctx->dpyAttr[dpy].fd);
   2738         ctx->dpyAttr[dpy].fd = -1;
   2739     }
   2740     // TODO: If HDMI is connected after the display has booted up,
   2741     // and the best configuration is different from the default
   2742     // then we need to deal with this appropriately.
   2743     ctx->mHDMIDisplay->configure();
   2744     updateDisplayInfo(ctx, dpy);
   2745     initCompositionResources(ctx, dpy);
   2746     ctx->dpyAttr[dpy].connected = true;
   2747 }
   2748 
   2749 // Handles offline events for HDMI. This can be used for offline events
   2750 // initiated by the HDMI driver and the CEC framework.
   2751 void handle_offline(hwc_context_t* ctx, int dpy) {
   2752     destroyCompositionResources(ctx, dpy);
   2753     // Clear all pipe resources and call a display commit to ensure
   2754     // that all the fd's are closed. This will ensure that the HDMI
   2755     // core turns off and that we receive an event the next time the
   2756     // cable is connected.
   2757     if (ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
   2758         clearPipeResources(ctx, dpy);
   2759     }
   2760     ctx->mHDMIDisplay->teardown();
   2761     resetDisplayInfo(ctx, dpy);
   2762     ctx->dpyAttr[dpy].connected = false;
   2763     ctx->dpyAttr[dpy].isActive = false;
   2764     //On 8994 due to hardware limitations, we enable bwc only when HDMI
   2765     //intf is inactive
   2766     if(qdutils::MDPVersion::getInstance().is8994() and
   2767             qdutils::MDPVersion::getInstance().supportsBWC()) {
   2768         ctx->mBWCEnabled = true;
   2769     }
   2770 }
   2771 
   2772 };//namespace qhwc
   2773