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