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