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