hwc_utils.cpp revision 5080cdee5662ba2eab9a058bda428217720dc694
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012-2014, The Linux Foundation All rights reserved.
4 *
5 * Not a Contribution, Apache license notifications and license are retained
6 * for attribution purposes only.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
21#define HWC_UTILS_DEBUG 0
22#include <math.h>
23#include <sys/ioctl.h>
24#include <linux/fb.h>
25#include <binder/IServiceManager.h>
26#include <EGL/egl.h>
27#include <cutils/properties.h>
28#include <utils/Trace.h>
29#include <gralloc_priv.h>
30#include <overlay.h>
31#include <overlayRotator.h>
32#include <overlayWriteback.h>
33#include "hwc_utils.h"
34#include "hwc_mdpcomp.h"
35#include "hwc_fbupdate.h"
36#include "hwc_ad.h"
37#include "mdp_version.h"
38#include "hwc_copybit.h"
39#include "hwc_dump_layers.h"
40#include "external.h"
41#include "virtual.h"
42#include "hwc_qclient.h"
43#include "QService.h"
44#include "comptype.h"
45#include "hwc_virtual.h"
46
47using namespace qClient;
48using namespace qService;
49using namespace android;
50using namespace overlay;
51using namespace overlay::utils;
52namespace ovutils = overlay::utils;
53
54#ifdef __cplusplus
55extern "C" {
56#endif
57
58EGLAPI EGLBoolean eglGpuPerfHintQCOM(EGLDisplay dpy, EGLContext ctx,
59                                           EGLint *attrib_list);
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#ifdef __cplusplus
71}
72#endif
73
74namespace qhwc {
75
76bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
77{
78    return !((xres > qdutils::MAX_DISPLAY_DIM &&
79                !isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY)) ||
80            (xres < MIN_DISPLAY_XRES || yres < MIN_DISPLAY_YRES));
81}
82
83void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig) {
84    //Store original display resolution.
85    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_orig = xres_orig;
86    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_orig = yres_orig;
87    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = false;
88
89    char property[PROPERTY_VALUE_MAX] = {'\0'};
90    char *yptr = NULL;
91    if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
92        yptr = strcasestr(property,"x");
93        int xres = atoi(property);
94        int yres = atoi(yptr + 1);
95        if (isValidResolution(ctx,xres,yres) &&
96                 xres != xres_orig && yres != yres_orig) {
97            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = xres;
98            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = yres;
99            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = true;
100        }
101    }
102}
103
104static int openFramebufferDevice(hwc_context_t *ctx)
105{
106    struct fb_fix_screeninfo finfo;
107    struct fb_var_screeninfo info;
108
109    int fb_fd = openFb(HWC_DISPLAY_PRIMARY);
110    if(fb_fd < 0) {
111        ALOGE("%s: Error Opening FB : %s", __FUNCTION__, strerror(errno));
112        return -errno;
113    }
114
115    if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &info) == -1) {
116        ALOGE("%s:Error in ioctl FBIOGET_VSCREENINFO: %s", __FUNCTION__,
117                                                       strerror(errno));
118        close(fb_fd);
119        return -errno;
120    }
121
122    if (int(info.width) <= 0 || int(info.height) <= 0) {
123        // the driver doesn't return that information
124        // default to 160 dpi
125        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
126        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
127    }
128
129    float xdpi = (info.xres * 25.4f) / info.width;
130    float ydpi = (info.yres * 25.4f) / info.height;
131
132#ifdef MSMFB_METADATA_GET
133    struct msmfb_metadata metadata;
134    memset(&metadata, 0 , sizeof(metadata));
135    metadata.op = metadata_op_frame_rate;
136
137    if (ioctl(fb_fd, MSMFB_METADATA_GET, &metadata) == -1) {
138        ALOGE("%s:Error retrieving panel frame rate: %s", __FUNCTION__,
139                                                      strerror(errno));
140        close(fb_fd);
141        return -errno;
142    }
143
144    float fps  = metadata.data.panel_frame_rate;
145#else
146    //XXX: Remove reserved field usage on all baselines
147    //The reserved[3] field is used to store FPS by the driver.
148    float fps  = info.reserved[3] & 0xFF;
149#endif
150
151    if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
152        ALOGE("%s:Error in ioctl FBIOGET_FSCREENINFO: %s", __FUNCTION__,
153                                                       strerror(errno));
154        close(fb_fd);
155        return -errno;
156    }
157
158    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = fb_fd;
159    //xres, yres may not be 32 aligned
160    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].stride = finfo.line_length /(info.xres/8);
161    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = info.xres;
162    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres;
163    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
164    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
165    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period = 1000000000l / fps;
166
167    //To change resolution of primary display
168    changeResolution(ctx, info.xres, info.yres);
169
170    //Unblank primary on first boot
171    if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
172        ALOGE("%s: Failed to unblank display", __FUNCTION__);
173        return -errno;
174    }
175    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive = true;
176
177    return 0;
178}
179
180void initContext(hwc_context_t *ctx)
181{
182    openFramebufferDevice(ctx);
183    ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
184    ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
185    ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
186    overlay::Overlay::initOverlay();
187    ctx->mOverlay = overlay::Overlay::getInstance();
188    ctx->mRotMgr = RotMgr::getInstance();
189
190    //Is created and destroyed only once for primary
191    //For external it could get created and destroyed multiple times depending
192    //on what external we connect to.
193    ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
194        IFBUpdate::getObject(ctx, HWC_DISPLAY_PRIMARY);
195
196    // Check if the target supports copybit compostion (dyn/mdp) to
197    // decide if we need to open the copybit module.
198    int compositionType =
199        qdutils::QCCompositionType::getInstance().getCompositionType();
200
201    // Only MDP copybit is used
202    if ((compositionType & (qdutils::COMPOSITION_TYPE_DYN |
203            qdutils::COMPOSITION_TYPE_MDP)) &&
204            (qdutils::MDPVersion::getInstance().getMDPVersion() ==
205            qdutils::MDP_V3_0_4)) {
206        ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
207                                                         HWC_DISPLAY_PRIMARY);
208    }
209
210    ctx->mExtDisplay = new ExternalDisplay(ctx);
211    ctx->mVirtualDisplay = new VirtualDisplay(ctx);
212    ctx->mVirtualonExtActive = false;
213    ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive = false;
214    ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = false;
215    ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false;
216    ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false;
217    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].mDownScaleMode= false;
218    ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
219    ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false;
220
221    ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
222         MDPComp::getObject(ctx, HWC_DISPLAY_PRIMARY);
223    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
224    ctx->mHWCVirtual = HWCVirtualBase::getObject();
225
226    for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
227        ctx->mHwcDebug[i] = new HwcDebug(i);
228        ctx->mLayerRotMap[i] = new LayerRotMap();
229        ctx->mAnimationState[i] = ANIMATION_STOPPED;
230        ctx->dpyAttr[i].mActionSafePresent = false;
231        ctx->dpyAttr[i].mAsWidthRatio = 0;
232        ctx->dpyAttr[i].mAsHeightRatio = 0;
233    }
234
235    for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
236        ctx->mPrevHwLayerCount[i] = 0;
237    }
238
239    MDPComp::init(ctx);
240    ctx->mAD = new AssertiveDisplay(ctx);
241
242    ctx->vstate.enable = false;
243    ctx->vstate.fakevsync = false;
244    ctx->mExtOrientation = 0;
245    ctx->numActiveDisplays = 1;
246
247    //Right now hwc starts the service but anybody could do it, or it could be
248    //independent process as well.
249    QService::init();
250    sp<IQClient> client = new QClient(ctx);
251    interface_cast<IQService>(
252            defaultServiceManager()->getService(
253            String16("display.qservice")))->connect(client);
254
255    // Initialize device orientation to its default orientation
256    ctx->deviceOrientation = 0;
257    ctx->mBufferMirrorMode = false;
258
259    // Read the system property to determine if downscale feature is enabled.
260    ctx->mMDPDownscaleEnabled = false;
261    char value[PROPERTY_VALUE_MAX];
262    if(property_get("sys.hwc.mdp_downscale_enabled", value, "false")
263            && !strcmp(value, "true")) {
264        ctx->mMDPDownscaleEnabled = true;
265    }
266
267    // Initialize gpu perfomance hint related parameters
268    property_get("sys.hwc.gpu_perf_mode", value, "0");
269    ctx->mGPUHintInfo.mGpuPerfModeEnable = atoi(value)? true : false;
270
271    ctx->mGPUHintInfo.mEGLDisplay = NULL;
272    ctx->mGPUHintInfo.mEGLContext = NULL;
273    ctx->mGPUHintInfo.mPrevCompositionGLES = false;
274    ctx->mGPUHintInfo.mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
275
276    ALOGI("Initializing Qualcomm Hardware Composer");
277    ALOGI("MDP version: %d", ctx->mMDP.version);
278}
279
280void closeContext(hwc_context_t *ctx)
281{
282    if(ctx->mOverlay) {
283        delete ctx->mOverlay;
284        ctx->mOverlay = NULL;
285    }
286
287    if(ctx->mRotMgr) {
288        delete ctx->mRotMgr;
289        ctx->mRotMgr = NULL;
290    }
291
292    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
293        if(ctx->mCopyBit[i]) {
294            delete ctx->mCopyBit[i];
295            ctx->mCopyBit[i] = NULL;
296        }
297    }
298
299    if(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd) {
300        close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd);
301        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1;
302    }
303
304    if(ctx->mExtDisplay) {
305        delete ctx->mExtDisplay;
306        ctx->mExtDisplay = NULL;
307    }
308
309    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
310        if(ctx->mFBUpdate[i]) {
311            delete ctx->mFBUpdate[i];
312            ctx->mFBUpdate[i] = NULL;
313        }
314        if(ctx->mMDPComp[i]) {
315            delete ctx->mMDPComp[i];
316            ctx->mMDPComp[i] = NULL;
317        }
318        if(ctx->mHwcDebug[i]) {
319            delete ctx->mHwcDebug[i];
320            ctx->mHwcDebug[i] = NULL;
321        }
322        if(ctx->mLayerRotMap[i]) {
323            delete ctx->mLayerRotMap[i];
324            ctx->mLayerRotMap[i] = NULL;
325        }
326    }
327    if(ctx->mHWCVirtual) {
328        delete ctx->mHWCVirtual;
329        ctx->mHWCVirtual = NULL;
330    }
331    if(ctx->mAD) {
332        delete ctx->mAD;
333        ctx->mAD = NULL;
334    }
335
336
337}
338
339
340void dumpsys_log(android::String8& buf, const char* fmt, ...)
341{
342    va_list varargs;
343    va_start(varargs, fmt);
344    buf.appendFormatV(fmt, varargs);
345    va_end(varargs);
346}
347
348int getExtOrientation(hwc_context_t* ctx) {
349    int extOrient = ctx->mExtOrientation;
350    if(ctx->mBufferMirrorMode)
351        extOrient = getMirrorModeOrientation(ctx);
352    return extOrient;
353}
354
355/* Calculates the destination position based on the action safe rectangle */
356void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& rect) {
357    // Position
358    int x = rect.left, y = rect.top;
359    int w = rect.right - rect.left;
360    int h = rect.bottom - rect.top;
361
362    if(!ctx->dpyAttr[dpy].mActionSafePresent)
363        return;
364   // Read action safe properties
365    int asWidthRatio = ctx->dpyAttr[dpy].mAsWidthRatio;
366    int asHeightRatio = ctx->dpyAttr[dpy].mAsHeightRatio;
367
368    float wRatio = 1.0;
369    float hRatio = 1.0;
370    float xRatio = 1.0;
371    float yRatio = 1.0;
372
373    int fbWidth = ctx->dpyAttr[dpy].xres;
374    int fbHeight = ctx->dpyAttr[dpy].yres;
375    if(ctx->dpyAttr[dpy].mDownScaleMode) {
376        // if downscale Mode is enabled for external, need to query
377        // the actual width and height, as that is the physical w & h
378         ctx->mExtDisplay->getAttributes(fbWidth, fbHeight);
379    }
380
381
382    // Since external is rotated 90, need to swap width/height
383    int extOrient = getExtOrientation(ctx);
384
385    if(extOrient & HWC_TRANSFORM_ROT_90)
386        swap(fbWidth, fbHeight);
387
388    float asX = 0;
389    float asY = 0;
390    float asW = fbWidth;
391    float asH = fbHeight;
392
393    // based on the action safe ratio, get the Action safe rectangle
394    asW = fbWidth * (1.0f -  asWidthRatio / 100.0f);
395    asH = fbHeight * (1.0f -  asHeightRatio / 100.0f);
396    asX = (fbWidth - asW) / 2;
397    asY = (fbHeight - asH) / 2;
398
399    // calculate the position ratio
400    xRatio = (float)x/fbWidth;
401    yRatio = (float)y/fbHeight;
402    wRatio = (float)w/fbWidth;
403    hRatio = (float)h/fbHeight;
404
405    //Calculate the position...
406    x = (xRatio * asW) + asX;
407    y = (yRatio * asH) + asY;
408    w = (wRatio * asW);
409    h = (hRatio * asH);
410
411    // Convert it back to hwc_rect_t
412    rect.left = x;
413    rect.top = y;
414    rect.right = w + rect.left;
415    rect.bottom = h + rect.top;
416
417    return;
418}
419
420/* Calculates the aspect ratio for based on src & dest */
421void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
422                                int srcHeight, hwc_rect_t& rect) {
423   int x =0, y =0;
424
425   if (srcWidth * destHeight > destWidth * srcHeight) {
426        srcHeight = destWidth * srcHeight / srcWidth;
427        srcWidth = destWidth;
428    } else if (srcWidth * destHeight < destWidth * srcHeight) {
429        srcWidth = destHeight * srcWidth / srcHeight;
430        srcHeight = destHeight;
431    } else {
432        srcWidth = destWidth;
433        srcHeight = destHeight;
434    }
435    if (srcWidth > destWidth) srcWidth = destWidth;
436    if (srcHeight > destHeight) srcHeight = destHeight;
437    x = (destWidth - srcWidth) / 2;
438    y = (destHeight - srcHeight) / 2;
439    ALOGD_IF(HWC_UTILS_DEBUG, "%s: AS Position: x = %d, y = %d w = %d h = %d",
440             __FUNCTION__, x, y, srcWidth , srcHeight);
441    // Convert it back to hwc_rect_t
442    rect.left = x;
443    rect.top = y;
444    rect.right = srcWidth + rect.left;
445    rect.bottom = srcHeight + rect.top;
446}
447
448// This function gets the destination position for Seconday display
449// based on the position and aspect ratio with orientation
450void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
451                            hwc_rect_t& inRect, hwc_rect_t& outRect) {
452    // Physical display resolution
453    float fbWidth  = ctx->dpyAttr[dpy].xres;
454    float fbHeight = ctx->dpyAttr[dpy].yres;
455    //display position(x,y,w,h) in correct aspectratio after rotation
456    int xPos = 0;
457    int yPos = 0;
458    float width = fbWidth;
459    float height = fbHeight;
460    // Width/Height used for calculation, after rotation
461    float actualWidth = fbWidth;
462    float actualHeight = fbHeight;
463
464    float wRatio = 1.0;
465    float hRatio = 1.0;
466    float xRatio = 1.0;
467    float yRatio = 1.0;
468    hwc_rect_t rect = {0, 0, (int)fbWidth, (int)fbHeight};
469
470    Dim inPos(inRect.left, inRect.top, inRect.right - inRect.left,
471                inRect.bottom - inRect.top);
472    Dim outPos(outRect.left, outRect.top, outRect.right - outRect.left,
473                outRect.bottom - outRect.top);
474
475    Whf whf(fbWidth, fbHeight, 0);
476    eTransform extorient = static_cast<eTransform>(extOrientation);
477    // To calculate the destination co-ordinates in the new orientation
478    preRotateSource(extorient, whf, inPos);
479
480    if(extOrientation & HAL_TRANSFORM_ROT_90) {
481        // Swap width/height for input position
482        swapWidthHeight(actualWidth, actualHeight);
483        getAspectRatioPosition(fbWidth, fbHeight, (int)actualWidth,
484                               (int)actualHeight, rect);
485        xPos = rect.left;
486        yPos = rect.top;
487        width = rect.right - rect.left;
488        height = rect.bottom - rect.top;
489    }
490    xRatio = inPos.x/actualWidth;
491    yRatio = inPos.y/actualHeight;
492    wRatio = inPos.w/actualWidth;
493    hRatio = inPos.h/actualHeight;
494
495
496    //Calculate the position...
497    outPos.x = (xRatio * width) + xPos;
498    outPos.y = (yRatio * height) + yPos;
499    outPos.w = wRatio * width;
500    outPos.h = hRatio * height;
501    ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio Position: x = %d,"
502                 "y = %d w = %d h = %d", __FUNCTION__, outPos.x, outPos.y,
503                 outPos.w, outPos.h);
504
505    // For sidesync, the dest fb will be in portrait orientation, and the crop
506    // will be updated to avoid the black side bands, and it will be upscaled
507    // to fit the dest RB, so recalculate
508    // the position based on the new width and height
509    if ((extOrientation & HWC_TRANSFORM_ROT_90) &&
510                        isOrientationPortrait(ctx)) {
511        hwc_rect_t r = {0, 0, 0, 0};
512        //Calculate the position
513        xRatio = (outPos.x - xPos)/width;
514        // GetaspectRatio -- tricky to get the correct aspect ratio
515        // But we need to do this.
516        getAspectRatioPosition(width, height, width, height, r);
517        xPos = r.left;
518        yPos = r.top;
519        float tempHeight = r.bottom - r.top;
520        yRatio = yPos/height;
521        wRatio = outPos.w/width;
522        hRatio = tempHeight/height;
523
524        //Map the coordinates back to Framebuffer domain
525        outPos.x = (xRatio * fbWidth);
526        outPos.y = (yRatio * fbHeight);
527        outPos.w = wRatio * fbWidth;
528        outPos.h = hRatio * fbHeight;
529
530        ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio for device in"
531                 "portrait: x = %d,y = %d w = %d h = %d", __FUNCTION__,
532                 outPos.x, outPos.y,
533                 outPos.w, outPos.h);
534    }
535    if(ctx->dpyAttr[dpy].mDownScaleMode) {
536        int extW, extH;
537        if(dpy == HWC_DISPLAY_EXTERNAL)
538            ctx->mExtDisplay->getAttributes(extW, extH);
539        else
540            ctx->mVirtualDisplay->getAttributes(extW, extH);
541        fbWidth  = ctx->dpyAttr[dpy].xres;
542        fbHeight = ctx->dpyAttr[dpy].yres;
543        //Calculate the position...
544        xRatio = outPos.x/fbWidth;
545        yRatio = outPos.y/fbHeight;
546        wRatio = outPos.w/fbWidth;
547        hRatio = outPos.h/fbHeight;
548
549        outPos.x = xRatio * extW;
550        outPos.y = yRatio * extH;
551        outPos.w = wRatio * extW;
552        outPos.h = hRatio * extH;
553    }
554    // Convert Dim to hwc_rect_t
555    outRect.left = outPos.x;
556    outRect.top = outPos.y;
557    outRect.right = outPos.x + outPos.w;
558    outRect.bottom = outPos.y + outPos.h;
559
560    return;
561}
562
563bool isPrimaryPortrait(hwc_context_t *ctx) {
564    int fbWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
565    int fbHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
566    if(fbWidth < fbHeight) {
567        return true;
568    }
569    return false;
570}
571
572bool isOrientationPortrait(hwc_context_t *ctx) {
573    if(isPrimaryPortrait(ctx)) {
574        return !(ctx->deviceOrientation & 0x1);
575    }
576    return (ctx->deviceOrientation & 0x1);
577}
578
579void calcExtDisplayPosition(hwc_context_t *ctx,
580                               private_handle_t *hnd,
581                               int dpy,
582                               hwc_rect_t& sourceCrop,
583                               hwc_rect_t& displayFrame,
584                               int& transform,
585                               ovutils::eTransform& orient) {
586    // Swap width and height when there is a 90deg transform
587    int extOrient = getExtOrientation(ctx);
588    if(dpy && !qdutils::MDPVersion::getInstance().is8x26()) {
589        if(!isYuvBuffer(hnd)) {
590            if(extOrient & HWC_TRANSFORM_ROT_90) {
591                int dstWidth = ctx->dpyAttr[dpy].xres;
592                int dstHeight = ctx->dpyAttr[dpy].yres;;
593                int srcWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
594                int srcHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
595                if(!isPrimaryPortrait(ctx)) {
596                    swap(srcWidth, srcHeight);
597                }                    // Get Aspect Ratio for external
598                getAspectRatioPosition(dstWidth, dstHeight, srcWidth,
599                                    srcHeight, displayFrame);
600                // Crop - this is needed, because for sidesync, the dest fb will
601                // be in portrait orientation, so update the crop to not show the
602                // black side bands.
603                if (isOrientationPortrait(ctx)) {
604                    sourceCrop = displayFrame;
605                    displayFrame.left = 0;
606                    displayFrame.top = 0;
607                    displayFrame.right = dstWidth;
608                    displayFrame.bottom = dstHeight;
609                }
610            }
611            if(ctx->dpyAttr[dpy].mDownScaleMode) {
612                int extW, extH;
613                // if downscale is enabled, map the co-ordinates to new
614                // domain(downscaled)
615                float fbWidth  = ctx->dpyAttr[dpy].xres;
616                float fbHeight = ctx->dpyAttr[dpy].yres;
617                // query MDP configured attributes
618                if(dpy == HWC_DISPLAY_EXTERNAL)
619                    ctx->mExtDisplay->getAttributes(extW, extH);
620                else
621                    ctx->mVirtualDisplay->getAttributes(extW, extH);
622                //Calculate the ratio...
623                float wRatio = ((float)extW)/fbWidth;
624                float hRatio = ((float)extH)/fbHeight;
625
626                //convert Dim to hwc_rect_t
627                displayFrame.left *= wRatio;
628                displayFrame.top *= hRatio;
629                displayFrame.right *= wRatio;
630                displayFrame.bottom *= hRatio;
631            }
632        }else {
633            if(extOrient || ctx->dpyAttr[dpy].mDownScaleMode) {
634                getAspectRatioPosition(ctx, dpy, extOrient,
635                                       displayFrame, displayFrame);
636            }
637        }
638        // If there is a external orientation set, use that
639        if(extOrient) {
640            transform = extOrient;
641            orient = static_cast<ovutils::eTransform >(extOrient);
642        }
643        // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
644        getActionSafePosition(ctx, dpy, displayFrame);
645    }
646}
647
648/* Returns the orientation which needs to be set on External for
649 *  SideSync/Buffer Mirrormode
650 */
651int getMirrorModeOrientation(hwc_context_t *ctx) {
652    int extOrientation = 0;
653    int deviceOrientation = ctx->deviceOrientation;
654    if(!isPrimaryPortrait(ctx))
655        deviceOrientation = (deviceOrientation + 1) % 4;
656     if (deviceOrientation == 0)
657         extOrientation = HWC_TRANSFORM_ROT_270;
658     else if (deviceOrientation == 1)//90
659         extOrientation = 0;
660     else if (deviceOrientation == 2)//180
661         extOrientation = HWC_TRANSFORM_ROT_90;
662     else if (deviceOrientation == 3)//270
663         extOrientation = HWC_TRANSFORM_FLIP_V | HWC_TRANSFORM_FLIP_H;
664
665    return extOrientation;
666}
667
668bool isDownscaleRequired(hwc_layer_1_t const* layer) {
669    hwc_rect_t displayFrame  = layer->displayFrame;
670    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
671    int dst_w, dst_h, src_w, src_h;
672    dst_w = displayFrame.right - displayFrame.left;
673    dst_h = displayFrame.bottom - displayFrame.top;
674    src_w = sourceCrop.right - sourceCrop.left;
675    src_h = sourceCrop.bottom - sourceCrop.top;
676
677    if(((src_w > dst_w) || (src_h > dst_h)))
678        return true;
679
680    return false;
681}
682bool needsScaling(hwc_layer_1_t const* layer) {
683    int dst_w, dst_h, src_w, src_h;
684    hwc_rect_t displayFrame  = layer->displayFrame;
685    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
686
687    dst_w = displayFrame.right - displayFrame.left;
688    dst_h = displayFrame.bottom - displayFrame.top;
689    src_w = sourceCrop.right - sourceCrop.left;
690    src_h = sourceCrop.bottom - sourceCrop.top;
691
692    if(((src_w != dst_w) || (src_h != dst_h)))
693        return true;
694
695    return false;
696}
697
698// Checks if layer needs scaling with split
699bool needsScalingWithSplit(hwc_context_t* ctx, hwc_layer_1_t const* layer,
700        const int& dpy) {
701
702    int src_width_l, src_height_l;
703    int src_width_r, src_height_r;
704    int dst_width_l, dst_height_l;
705    int dst_width_r, dst_height_r;
706    int hw_w = ctx->dpyAttr[dpy].xres;
707    int hw_h = ctx->dpyAttr[dpy].yres;
708    hwc_rect_t cropL, dstL, cropR, dstR;
709    const int lSplit = getLeftSplit(ctx, dpy);
710    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
711    hwc_rect_t displayFrame  = layer->displayFrame;
712    private_handle_t *hnd = (private_handle_t *)layer->handle;
713
714    cropL = sourceCrop;
715    dstL = displayFrame;
716    hwc_rect_t scissorL = { 0, 0, lSplit, hw_h };
717    scissorL = getIntersection(ctx->mViewFrame[dpy], scissorL);
718    qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0);
719
720    cropR = sourceCrop;
721    dstR = displayFrame;
722    hwc_rect_t scissorR = { lSplit, 0, hw_w, hw_h };
723    scissorR = getIntersection(ctx->mViewFrame[dpy], scissorR);
724    qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0);
725
726    // Sanitize Crop to stitch
727    sanitizeSourceCrop(cropL, cropR, hnd);
728
729    // Calculate the left dst
730    dst_width_l = dstL.right - dstL.left;
731    dst_height_l = dstL.bottom - dstL.top;
732    src_width_l = cropL.right - cropL.left;
733    src_height_l = cropL.bottom - cropL.top;
734
735    // check if there is any scaling on the left
736    if(((src_width_l != dst_width_l) || (src_height_l != dst_height_l)))
737        return true;
738
739    // Calculate the right dst
740    dst_width_r = dstR.right - dstR.left;
741    dst_height_r = dstR.bottom - dstR.top;
742    src_width_r = cropR.right - cropR.left;
743    src_height_r = cropR.bottom - cropR.top;
744
745    // check if there is any scaling on the right
746    if(((src_width_r != dst_width_r) || (src_height_r != dst_height_r)))
747        return true;
748
749    return false;
750}
751
752bool isAlphaScaled(hwc_layer_1_t const* layer) {
753    if(needsScaling(layer) && isAlphaPresent(layer)) {
754        return true;
755    }
756    return false;
757}
758
759bool isAlphaPresent(hwc_layer_1_t const* layer) {
760    private_handle_t *hnd = (private_handle_t *)layer->handle;
761    if(hnd) {
762        int format = hnd->format;
763        switch(format) {
764        case HAL_PIXEL_FORMAT_RGBA_8888:
765        case HAL_PIXEL_FORMAT_BGRA_8888:
766            // In any more formats with Alpha go here..
767            return true;
768        default : return false;
769        }
770    }
771    return false;
772}
773
774static void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
775        hwc_rect_t& crop, hwc_rect_t& dst) {
776    int hw_w = ctx->dpyAttr[dpy].xres;
777    int hw_h = ctx->dpyAttr[dpy].yres;
778    if(dst.left < 0 || dst.top < 0 ||
779            dst.right > hw_w || dst.bottom > hw_h) {
780        hwc_rect_t scissor = {0, 0, hw_w, hw_h };
781        scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
782        qhwc::calculate_crop_rects(crop, dst, scissor, transform);
783    }
784}
785
786static void trimList(hwc_context_t *ctx, hwc_display_contents_1_t *list,
787        const int& dpy) {
788    for(uint32_t i = 0; i < list->numHwLayers - 1; i++) {
789        hwc_layer_1_t *layer = &list->hwLayers[i];
790        hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
791        trimLayer(ctx, dpy,
792                list->hwLayers[i].transform,
793                (hwc_rect_t&)crop,
794                (hwc_rect_t&)list->hwLayers[i].displayFrame);
795        layer->sourceCropf.left = crop.left;
796        layer->sourceCropf.right = crop.right;
797        layer->sourceCropf.top = crop.top;
798        layer->sourceCropf.bottom = crop.bottom;
799    }
800}
801
802hwc_rect_t calculateDisplayViewFrame(hwc_context_t *ctx, int dpy) {
803    int dstWidth = ctx->dpyAttr[dpy].xres;
804    int dstHeight = ctx->dpyAttr[dpy].yres;
805    int srcWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
806    int srcHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
807    // default we assume viewframe as a full frame for primary display
808    hwc_rect outRect = {0, 0, dstWidth, dstHeight};
809    if(dpy) {
810        // swap srcWidth and srcHeight, if the device orientation is 90 or 270.
811        if(ctx->deviceOrientation & 0x1) {
812            swap(srcWidth, srcHeight);
813        }
814        // Get Aspect Ratio for external
815        getAspectRatioPosition(dstWidth, dstHeight, srcWidth,
816                            srcHeight, outRect);
817    }
818    ALOGD_IF(HWC_UTILS_DEBUG, "%s: view frame for dpy %d is [%d %d %d %d]",
819        __FUNCTION__, dpy, outRect.left, outRect.top,
820        outRect.right, outRect.bottom);
821    return outRect;
822}
823
824void setListStats(hwc_context_t *ctx,
825        hwc_display_contents_1_t *list, int dpy) {
826    const int prevYuvCount = ctx->listStats[dpy].yuvCount;
827    memset(&ctx->listStats[dpy], 0, sizeof(ListStats));
828    ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
829    ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
830    ctx->listStats[dpy].skipCount = 0;
831    ctx->listStats[dpy].preMultipliedAlpha = false;
832    ctx->listStats[dpy].isSecurePresent = false;
833    ctx->listStats[dpy].yuvCount = 0;
834    char property[PROPERTY_VALUE_MAX];
835    ctx->listStats[dpy].extOnlyLayerIndex = -1;
836    ctx->listStats[dpy].isDisplayAnimating = false;
837    ctx->listStats[dpy].roi = ovutils::Dim(0, 0,
838                      (int)ctx->dpyAttr[dpy].xres, (int)ctx->dpyAttr[dpy].yres);
839    ctx->listStats[dpy].secureUI = false;
840    ctx->listStats[dpy].yuv4k2kCount = 0;
841    ctx->mViewFrame[dpy] = (hwc_rect_t){0, 0, 0, 0};
842    ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
843
844    trimList(ctx, list, dpy);
845    optimizeLayerRects(list);
846
847    // Calculate view frame of ext display from primary resolution
848    // and primary device orientation.
849    ctx->mViewFrame[dpy] = calculateDisplayViewFrame(ctx, dpy);
850
851    for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
852        hwc_layer_1_t const* layer = &list->hwLayers[i];
853        private_handle_t *hnd = (private_handle_t *)layer->handle;
854
855#ifdef QCOM_BSP
856        if (layer->flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
857            ctx->listStats[dpy].isDisplayAnimating = true;
858        }
859        if(isSecureDisplayBuffer(hnd)) {
860            ctx->listStats[dpy].secureUI = true;
861        }
862#endif
863        // continue if number of app layers exceeds MAX_NUM_APP_LAYERS
864        if(ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS)
865            continue;
866
867        //reset yuv indices
868        ctx->listStats[dpy].yuvIndices[i] = -1;
869        ctx->listStats[dpy].yuv4k2kIndices[i] = -1;
870
871        if (isSecureBuffer(hnd)) {
872            ctx->listStats[dpy].isSecurePresent = true;
873        }
874
875        if (isSkipLayer(&list->hwLayers[i])) {
876            ctx->listStats[dpy].skipCount++;
877        }
878
879        if (UNLIKELY(isYuvBuffer(hnd))) {
880            int& yuvCount = ctx->listStats[dpy].yuvCount;
881            ctx->listStats[dpy].yuvIndices[yuvCount] = i;
882            yuvCount++;
883
884            if(UNLIKELY(is4kx2kYuvBuffer(hnd))){
885                int& yuv4k2kCount = ctx->listStats[dpy].yuv4k2kCount;
886                ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = i;
887                yuv4k2kCount++;
888            }
889
890            if((layer->transform & HWC_TRANSFORM_ROT_90) &&
891               canUseRotator(ctx, dpy)) {
892               if(ctx->mOverlay->isPipeTypeAttached(OV_MDP_PIPE_DMA))
893                  ctx->isPaddingRound = true;
894               Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
895            }
896        }
897        if(layer->blending == HWC_BLENDING_PREMULT)
898            ctx->listStats[dpy].preMultipliedAlpha = true;
899
900
901        if(UNLIKELY(isExtOnly(hnd))){
902            ctx->listStats[dpy].extOnlyLayerIndex = i;
903        }
904    }
905    if(ctx->listStats[dpy].yuvCount > 0) {
906        if (property_get("hw.cabl.yuv", property, NULL) > 0) {
907            if (atoi(property) != 1) {
908                property_set("hw.cabl.yuv", "1");
909            }
910        }
911    } else {
912        if (property_get("hw.cabl.yuv", property, NULL) > 0) {
913            if (atoi(property) != 0) {
914                property_set("hw.cabl.yuv", "0");
915            }
916        }
917    }
918    if(dpy) {
919        //uncomment the below code for testing purpose.
920        /* char value[PROPERTY_VALUE_MAX];
921        property_get("sys.ext_orientation", value, "0");
922        // Assuming the orientation value is in terms of HAL_TRANSFORM,
923        // This needs mapping to HAL, if its in different convention
924        ctx->mExtOrientation = atoi(value); */
925        // Assuming the orientation value is in terms of HAL_TRANSFORM,
926        // This needs mapping to HAL, if its in different convention
927        if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
928            ALOGD_IF(HWC_UTILS_DEBUG, "%s: ext orientation = %d"
929                     "BufferMirrorMode = %d", __FUNCTION__,
930                     ctx->mExtOrientation, ctx->mBufferMirrorMode);
931            if(ctx->mOverlay->isPipeTypeAttached(OV_MDP_PIPE_DMA)) {
932                ctx->isPaddingRound = true;
933            }
934            Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
935        }
936    }
937
938    //The marking of video begin/end is useful on some targets where we need
939    //to have a padding round to be able to shift pipes across mixers.
940    if(prevYuvCount != ctx->listStats[dpy].yuvCount) {
941        ctx->mVideoTransFlag = true;
942    }
943
944    if(dpy == HWC_DISPLAY_PRIMARY) {
945        ctx->mAD->markDoable(ctx, list);
946    }
947}
948
949
950static void calc_cut(double& leftCutRatio, double& topCutRatio,
951        double& rightCutRatio, double& bottomCutRatio, int orient) {
952    if(orient & HAL_TRANSFORM_FLIP_H) {
953        swap(leftCutRatio, rightCutRatio);
954    }
955    if(orient & HAL_TRANSFORM_FLIP_V) {
956        swap(topCutRatio, bottomCutRatio);
957    }
958    if(orient & HAL_TRANSFORM_ROT_90) {
959        //Anti clock swapping
960        double tmpCutRatio = leftCutRatio;
961        leftCutRatio = topCutRatio;
962        topCutRatio = rightCutRatio;
963        rightCutRatio = bottomCutRatio;
964        bottomCutRatio = tmpCutRatio;
965    }
966}
967
968bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer) {
969    if((ctx->mMDP.version < qdutils::MDSS_V5) &&
970       (ctx->mMDP.version > qdutils::MDP_V3_0) &&
971        ctx->mSecuring) {
972        return true;
973    }
974    if (isSecureModePolicy(ctx->mMDP.version)) {
975        private_handle_t *hnd = (private_handle_t *)layer->handle;
976        if(ctx->mSecureMode) {
977            if (! isSecureBuffer(hnd)) {
978                ALOGD_IF(HWC_UTILS_DEBUG,"%s:Securing Turning ON ...",
979                         __FUNCTION__);
980                return true;
981            }
982        } else {
983            if (isSecureBuffer(hnd)) {
984                ALOGD_IF(HWC_UTILS_DEBUG,"%s:Securing Turning OFF ...",
985                         __FUNCTION__);
986                return true;
987            }
988        }
989    }
990    return false;
991}
992
993bool isSecureModePolicy(int mdpVersion) {
994    if (mdpVersion < qdutils::MDSS_V5)
995        return true;
996    else
997        return false;
998}
999
1000// returns true if Action safe dimensions are set and target supports Actionsafe
1001bool isActionSafePresent(hwc_context_t *ctx, int dpy) {
1002    // if external supports underscan, do nothing
1003    // it will be taken care in the driver
1004    // Disable Action safe for 8974 due to HW limitation for downscaling
1005    // layers with overlapped region
1006    // Disable Actionsafe for non HDMI displays.
1007    if(!(dpy == HWC_DISPLAY_EXTERNAL) ||
1008        qdutils::MDPVersion::getInstance().is8x74v2() ||
1009        ctx->mExtDisplay->isCEUnderscanSupported()) {
1010        return false;
1011    }
1012
1013    char value[PROPERTY_VALUE_MAX];
1014    // Read action safe properties
1015    property_get("persist.sys.actionsafe.width", value, "0");
1016    ctx->dpyAttr[dpy].mAsWidthRatio = atoi(value);
1017    property_get("persist.sys.actionsafe.height", value, "0");
1018    ctx->dpyAttr[dpy].mAsHeightRatio = atoi(value);
1019
1020    if(!ctx->dpyAttr[dpy].mAsWidthRatio && !ctx->dpyAttr[dpy].mAsHeightRatio) {
1021        //No action safe ratio set, return
1022        return false;
1023    }
1024    return true;
1025}
1026
1027int getBlending(int blending) {
1028    switch(blending) {
1029    case HWC_BLENDING_NONE:
1030        return overlay::utils::OVERLAY_BLENDING_OPAQUE;
1031    case HWC_BLENDING_PREMULT:
1032        return overlay::utils::OVERLAY_BLENDING_PREMULT;
1033    case HWC_BLENDING_COVERAGE :
1034    default:
1035        return overlay::utils::OVERLAY_BLENDING_COVERAGE;
1036    }
1037}
1038
1039//Crops source buffer against destination and FB boundaries
1040void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
1041                          const hwc_rect_t& scissor, int orient) {
1042
1043    int& crop_l = crop.left;
1044    int& crop_t = crop.top;
1045    int& crop_r = crop.right;
1046    int& crop_b = crop.bottom;
1047    int crop_w = crop.right - crop.left;
1048    int crop_h = crop.bottom - crop.top;
1049
1050    int& dst_l = dst.left;
1051    int& dst_t = dst.top;
1052    int& dst_r = dst.right;
1053    int& dst_b = dst.bottom;
1054    int dst_w = abs(dst.right - dst.left);
1055    int dst_h = abs(dst.bottom - dst.top);
1056
1057    const int& sci_l = scissor.left;
1058    const int& sci_t = scissor.top;
1059    const int& sci_r = scissor.right;
1060    const int& sci_b = scissor.bottom;
1061
1062    double leftCutRatio = 0.0, rightCutRatio = 0.0, topCutRatio = 0.0,
1063            bottomCutRatio = 0.0;
1064
1065    if(dst_l < sci_l) {
1066        leftCutRatio = (double)(sci_l - dst_l) / (double)dst_w;
1067        dst_l = sci_l;
1068    }
1069
1070    if(dst_r > sci_r) {
1071        rightCutRatio = (double)(dst_r - sci_r) / (double)dst_w;
1072        dst_r = sci_r;
1073    }
1074
1075    if(dst_t < sci_t) {
1076        topCutRatio = (double)(sci_t - dst_t) / (double)dst_h;
1077        dst_t = sci_t;
1078    }
1079
1080    if(dst_b > sci_b) {
1081        bottomCutRatio = (double)(dst_b - sci_b) / (double)dst_h;
1082        dst_b = sci_b;
1083    }
1084
1085    calc_cut(leftCutRatio, topCutRatio, rightCutRatio, bottomCutRatio, orient);
1086    crop_l += (int)round((double)crop_w * leftCutRatio);
1087    crop_t += (int)round((double)crop_h * topCutRatio);
1088    crop_r -= (int)round((double)crop_w * rightCutRatio);
1089    crop_b -= (int)round((double)crop_h * bottomCutRatio);
1090}
1091
1092bool areLayersIntersecting(const hwc_layer_1_t* layer1,
1093        const hwc_layer_1_t* layer2) {
1094    hwc_rect_t irect = getIntersection(layer1->displayFrame,
1095            layer2->displayFrame);
1096    return isValidRect(irect);
1097}
1098
1099bool isValidRect(const hwc_rect& rect)
1100{
1101   return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
1102}
1103
1104/* computes the intersection of two rects */
1105hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2)
1106{
1107   hwc_rect_t res;
1108
1109   if(!isValidRect(rect1) || !isValidRect(rect2)){
1110      return (hwc_rect_t){0, 0, 0, 0};
1111   }
1112
1113
1114   res.left = max(rect1.left, rect2.left);
1115   res.top = max(rect1.top, rect2.top);
1116   res.right = min(rect1.right, rect2.right);
1117   res.bottom = min(rect1.bottom, rect2.bottom);
1118
1119   if(!isValidRect(res))
1120      return (hwc_rect_t){0, 0, 0, 0};
1121
1122   return res;
1123}
1124
1125/* computes the union of two rects */
1126hwc_rect_t getUnion(const hwc_rect &rect1, const hwc_rect &rect2)
1127{
1128   hwc_rect_t res;
1129
1130   if(!isValidRect(rect1)){
1131      return rect2;
1132   }
1133
1134   if(!isValidRect(rect2)){
1135      return rect1;
1136   }
1137
1138   res.left = min(rect1.left, rect2.left);
1139   res.top = min(rect1.top, rect2.top);
1140   res.right =  max(rect1.right, rect2.right);
1141   res.bottom =  max(rect1.bottom, rect2.bottom);
1142
1143   return res;
1144}
1145
1146/* Not a geometrical rect deduction. Deducts rect2 from rect1 only if it results
1147 * a single rect */
1148hwc_rect_t deductRect(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
1149
1150   hwc_rect_t res = rect1;
1151
1152   if((rect1.left == rect2.left) && (rect1.right == rect2.right)) {
1153      if((rect1.top == rect2.top) && (rect2.bottom <= rect1.bottom))
1154         res.top = rect2.bottom;
1155      else if((rect1.bottom == rect2.bottom)&& (rect2.top >= rect1.top))
1156         res.bottom = rect2.top;
1157   }
1158   else if((rect1.top == rect2.top) && (rect1.bottom == rect2.bottom)) {
1159      if((rect1.left == rect2.left) && (rect2.right <= rect1.right))
1160         res.left = rect2.right;
1161      else if((rect1.right == rect2.right)&& (rect2.left >= rect1.left))
1162         res.right = rect2.left;
1163   }
1164   return res;
1165}
1166
1167void optimizeLayerRects(const hwc_display_contents_1_t *list) {
1168    int i=list->numHwLayers-2;
1169    while(i > 0) {
1170        //see if there is no blending required.
1171        //If it is opaque see if we can substract this region from below
1172        //layers.
1173        if(list->hwLayers[i].blending == HWC_BLENDING_NONE) {
1174            int j= i-1;
1175            hwc_rect_t& topframe =
1176                (hwc_rect_t&)list->hwLayers[i].displayFrame;
1177            while(j >= 0) {
1178               if(!needsScaling(&list->hwLayers[j])) {
1179                  hwc_layer_1_t* layer = (hwc_layer_1_t*)&list->hwLayers[j];
1180                  hwc_rect_t& bottomframe = layer->displayFrame;
1181                  hwc_rect_t bottomCrop =
1182                      integerizeSourceCrop(layer->sourceCropf);
1183                  int transform =layer->transform;
1184
1185                  hwc_rect_t irect = getIntersection(bottomframe, topframe);
1186                  if(isValidRect(irect)) {
1187                     hwc_rect_t dest_rect;
1188                     //if intersection is valid rect, deduct it
1189                     dest_rect  = deductRect(bottomframe, irect);
1190                     qhwc::calculate_crop_rects(bottomCrop, bottomframe,
1191                                                dest_rect, transform);
1192                     //Update layer sourceCropf
1193                     layer->sourceCropf.left = bottomCrop.left;
1194                     layer->sourceCropf.top = bottomCrop.top;
1195                     layer->sourceCropf.right = bottomCrop.right;
1196                     layer->sourceCropf.bottom = bottomCrop.bottom;
1197                  }
1198               }
1199               j--;
1200            }
1201        }
1202        i--;
1203    }
1204}
1205
1206void getNonWormholeRegion(hwc_display_contents_1_t* list,
1207                              hwc_rect_t& nwr)
1208{
1209    uint32_t last = list->numHwLayers - 1;
1210    hwc_rect_t fbDisplayFrame = list->hwLayers[last].displayFrame;
1211    //Initiliaze nwr to first frame
1212    nwr.left =  list->hwLayers[0].displayFrame.left;
1213    nwr.top =  list->hwLayers[0].displayFrame.top;
1214    nwr.right =  list->hwLayers[0].displayFrame.right;
1215    nwr.bottom =  list->hwLayers[0].displayFrame.bottom;
1216
1217    for (uint32_t i = 1; i < last; i++) {
1218        hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
1219        nwr = getUnion(nwr, displayFrame);
1220    }
1221
1222    //Intersect with the framebuffer
1223    nwr = getIntersection(nwr, fbDisplayFrame);
1224}
1225
1226bool isExternalActive(hwc_context_t* ctx) {
1227    return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
1228}
1229
1230void closeAcquireFds(hwc_display_contents_1_t* list) {
1231    if(LIKELY(list)) {
1232        for(uint32_t i = 0; i < list->numHwLayers; i++) {
1233            //Close the acquireFenceFds
1234            //HWC_FRAMEBUFFER are -1 already by SF, rest we close.
1235            if(list->hwLayers[i].acquireFenceFd >= 0) {
1236                close(list->hwLayers[i].acquireFenceFd);
1237                list->hwLayers[i].acquireFenceFd = -1;
1238            }
1239        }
1240        //Writeback
1241        if(list->outbufAcquireFenceFd >= 0) {
1242            close(list->outbufAcquireFenceFd);
1243            list->outbufAcquireFenceFd = -1;
1244        }
1245    }
1246}
1247
1248int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
1249        int fd) {
1250    ATRACE_CALL();
1251    int ret = 0;
1252    int acquireFd[MAX_NUM_APP_LAYERS];
1253    int count = 0;
1254    int releaseFd = -1;
1255    int retireFd = -1;
1256    int fbFd = -1;
1257    bool swapzero = false;
1258
1259    struct mdp_buf_sync data;
1260    memset(&data, 0, sizeof(data));
1261    data.acq_fen_fd = acquireFd;
1262    data.rel_fen_fd = &releaseFd;
1263    data.retire_fen_fd = &retireFd;
1264    data.flags = MDP_BUF_SYNC_FLAG_RETIRE_FENCE;
1265
1266    char property[PROPERTY_VALUE_MAX];
1267    if(property_get("debug.egl.swapinterval", property, "1") > 0) {
1268        if(atoi(property) == 0)
1269            swapzero = true;
1270    }
1271
1272    bool isExtAnimating = false;
1273    if(dpy)
1274       isExtAnimating = ctx->listStats[dpy].isDisplayAnimating;
1275
1276    //Send acquireFenceFds to rotator
1277    for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
1278        int rotFd = ctx->mRotMgr->getRotDevFd();
1279        int rotReleaseFd = -1;
1280        overlay::Rotator* currRot = ctx->mLayerRotMap[dpy]->getRot(i);
1281        hwc_layer_1_t* currLayer = ctx->mLayerRotMap[dpy]->getLayer(i);
1282        if((currRot == NULL) || (currLayer == NULL)) {
1283            continue;
1284        }
1285        struct mdp_buf_sync rotData;
1286        memset(&rotData, 0, sizeof(rotData));
1287        rotData.acq_fen_fd =
1288                &currLayer->acquireFenceFd;
1289        rotData.rel_fen_fd = &rotReleaseFd; //driver to populate this
1290        rotData.session_id = currRot->getSessId();
1291        int ret = 0;
1292        ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
1293        if(ret < 0) {
1294            ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed for rot sync, err=%s",
1295                    __FUNCTION__, strerror(errno));
1296        } else {
1297            close(currLayer->acquireFenceFd);
1298            //For MDP to wait on.
1299            currLayer->acquireFenceFd =
1300                    dup(rotReleaseFd);
1301            //A buffer is free to be used by producer as soon as its copied to
1302            //rotator
1303            currLayer->releaseFenceFd =
1304                    rotReleaseFd;
1305        }
1306    }
1307
1308    //Accumulate acquireFenceFds for MDP Overlays
1309    if(list->outbufAcquireFenceFd >= 0) {
1310        //Writeback output buffer
1311        acquireFd[count++] = list->outbufAcquireFenceFd;
1312    }
1313
1314    for(uint32_t i = 0; i < list->numHwLayers; i++) {
1315        if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
1316                        list->hwLayers[i].acquireFenceFd >= 0) {
1317            if(UNLIKELY(swapzero))
1318                acquireFd[count++] = -1;
1319            else
1320                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
1321        }
1322        if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
1323            if(UNLIKELY(swapzero))
1324                acquireFd[count++] = -1;
1325            else if(fd >= 0) {
1326                //set the acquireFD from fd - which is coming from c2d
1327                acquireFd[count++] = fd;
1328                // Buffer sync IOCTL should be async when using c2d fence is
1329                // used
1330                data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
1331            } else if(list->hwLayers[i].acquireFenceFd >= 0)
1332                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
1333        }
1334    }
1335
1336    data.acq_fen_fd_cnt = count;
1337    fbFd = ctx->dpyAttr[dpy].fd;
1338
1339    //Waits for acquire fences, returns a release fence
1340    if(LIKELY(!swapzero)) {
1341        uint64_t start = systemTime();
1342        ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
1343        ALOGD_IF(HWC_UTILS_DEBUG, "%s: time taken for MSMFB_BUFFER_SYNC IOCTL = %d",
1344                            __FUNCTION__, (size_t) ns2ms(systemTime() - start));
1345    }
1346
1347    if(ret < 0) {
1348        ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed, err=%s",
1349                  __FUNCTION__, strerror(errno));
1350        ALOGE("%s: acq_fen_fd_cnt=%d flags=%d fd=%d dpy=%d numHwLayers=%d",
1351              __FUNCTION__, data.acq_fen_fd_cnt, data.flags, fbFd,
1352              dpy, list->numHwLayers);
1353    }
1354
1355    LayerProp *layerProp = ctx->layerProp[dpy];
1356    for(uint32_t i = 0; i < list->numHwLayers; i++) {
1357        if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
1358           list->hwLayers[i].compositionType == HWC_BLIT ||
1359           list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
1360            //Populate releaseFenceFds.
1361            if(UNLIKELY(swapzero)) {
1362                list->hwLayers[i].releaseFenceFd = -1;
1363            } else if(isExtAnimating) {
1364                // Release all the app layer fds immediately,
1365                // if animation is in progress.
1366                list->hwLayers[i].releaseFenceFd = -1;
1367            } else if(list->hwLayers[i].releaseFenceFd < 0 ) {
1368                //If rotator has not already populated this field
1369                if(list->hwLayers[i].compositionType == HWC_BLIT) {
1370                    //For Blit, the app layers should be released when the Blit is
1371                    //complete. This fd was passed from copybit->draw
1372                    list->hwLayers[i].releaseFenceFd = dup(fd);
1373                } else {
1374                    list->hwLayers[i].releaseFenceFd = dup(releaseFd);
1375                }
1376            }
1377        }
1378    }
1379
1380    if(fd >= 0) {
1381        close(fd);
1382        fd = -1;
1383    }
1384
1385    if (ctx->mCopyBit[dpy])
1386        ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
1387
1388    //Signals when MDP finishes reading rotator buffers.
1389    ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
1390    close(releaseFd);
1391    releaseFd = -1;
1392
1393    if(UNLIKELY(swapzero)) {
1394        list->retireFenceFd = -1;
1395    } else {
1396        list->retireFenceFd = retireFd;
1397    }
1398    return ret;
1399}
1400
1401void setMdpFlags(hwc_layer_1_t *layer,
1402        ovutils::eMdpFlags &mdpFlags,
1403        int rotDownscale, int transform) {
1404    private_handle_t *hnd = (private_handle_t *)layer->handle;
1405    MetaData_t *metadata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
1406
1407    if(layer->blending == HWC_BLENDING_PREMULT) {
1408        ovutils::setMdpFlags(mdpFlags,
1409                ovutils::OV_MDP_BLEND_FG_PREMULT);
1410    }
1411
1412    if(isYuvBuffer(hnd)) {
1413        if(isSecureBuffer(hnd)) {
1414            ovutils::setMdpFlags(mdpFlags,
1415                    ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
1416        }
1417        if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
1418                metadata->interlaced) {
1419            ovutils::setMdpFlags(mdpFlags,
1420                    ovutils::OV_MDP_DEINTERLACE);
1421        }
1422        //Pre-rotation will be used using rotator.
1423        if(transform & HWC_TRANSFORM_ROT_90) {
1424            ovutils::setMdpFlags(mdpFlags,
1425                    ovutils::OV_MDP_SOURCE_ROTATED_90);
1426        }
1427    }
1428
1429    if(isSecureDisplayBuffer(hnd)) {
1430        // Secure display needs both SECURE_OVERLAY and SECURE_DISPLAY_OV
1431        ovutils::setMdpFlags(mdpFlags,
1432                             ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
1433        ovutils::setMdpFlags(mdpFlags,
1434                             ovutils::OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION);
1435    }
1436    //No 90 component and no rot-downscale then flips done by MDP
1437    //If we use rot then it might as well do flips
1438    if(!(transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
1439        if(transform & HWC_TRANSFORM_FLIP_H) {
1440            ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
1441        }
1442
1443        if(transform & HWC_TRANSFORM_FLIP_V) {
1444            ovutils::setMdpFlags(mdpFlags,  ovutils::OV_MDP_FLIP_V);
1445        }
1446    }
1447
1448    if(metadata &&
1449        ((metadata->operation & PP_PARAM_HSIC)
1450        || (metadata->operation & PP_PARAM_IGC)
1451        || (metadata->operation & PP_PARAM_SHARP2))) {
1452        ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_PP_EN);
1453    }
1454}
1455
1456int configRotator(Rotator *rot, Whf& whf,
1457        hwc_rect_t& crop, const eMdpFlags& mdpFlags,
1458        const eTransform& orient, const int& downscale) {
1459
1460    // Fix alignments for TILED format
1461    if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
1462                            whf.format == MDP_Y_CBCR_H2V2_TILE) {
1463        whf.w =  utils::alignup(whf.w, 64);
1464        whf.h = utils::alignup(whf.h, 32);
1465    }
1466    rot->setSource(whf);
1467
1468    if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
1469        qdutils::MDSS_V5) {
1470        uint32_t crop_w = (crop.right - crop.left);
1471        uint32_t crop_h = (crop.bottom - crop.top);
1472        if (ovutils::isYuv(whf.format)) {
1473            ovutils::normalizeCrop((uint32_t&)crop.left, crop_w);
1474            ovutils::normalizeCrop((uint32_t&)crop.top, crop_h);
1475            // For interlaced, crop.h should be 4-aligned
1476            if ((mdpFlags & ovutils::OV_MDP_DEINTERLACE) && (crop_h % 4))
1477                crop_h = ovutils::aligndown(crop_h, 4);
1478            crop.right = crop.left + crop_w;
1479            crop.bottom = crop.top + crop_h;
1480        }
1481        Dim rotCrop(crop.left, crop.top, crop_w, crop_h);
1482        rot->setCrop(rotCrop);
1483    }
1484
1485    rot->setFlags(mdpFlags);
1486    rot->setTransform(orient);
1487    rot->setDownscale(downscale);
1488    if(!rot->commit()) return -1;
1489    return 0;
1490}
1491
1492int configMdp(Overlay *ov, const PipeArgs& parg,
1493        const eTransform& orient, const hwc_rect_t& crop,
1494        const hwc_rect_t& pos, const MetaData_t *metadata,
1495        const eDest& dest) {
1496    ov->setSource(parg, dest);
1497    ov->setTransform(orient, dest);
1498
1499    int crop_w = crop.right - crop.left;
1500    int crop_h = crop.bottom - crop.top;
1501    Dim dcrop(crop.left, crop.top, crop_w, crop_h);
1502    ov->setCrop(dcrop, dest);
1503
1504    int posW = pos.right - pos.left;
1505    int posH = pos.bottom - pos.top;
1506    Dim position(pos.left, pos.top, posW, posH);
1507    ov->setPosition(position, dest);
1508
1509    if (metadata)
1510        ov->setVisualParams(*metadata, dest);
1511
1512    if (!ov->commit(dest)) {
1513        return -1;
1514    }
1515    return 0;
1516}
1517
1518int configColorLayer(hwc_context_t *ctx, hwc_layer_1_t *layer,
1519        const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
1520        eIsFg& isFg, const eDest& dest) {
1521
1522    hwc_rect_t dst = layer->displayFrame;
1523    trimLayer(ctx, dpy, 0, dst, dst);
1524
1525    int w = ctx->dpyAttr[dpy].xres;
1526    int h = ctx->dpyAttr[dpy].yres;
1527    int dst_w = dst.right - dst.left;
1528    int dst_h = dst.bottom - dst.top;
1529    uint32_t color = layer->transform;
1530    Whf whf(w, h, getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888), 0);
1531
1532    ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SOLID_FILL);
1533    if (layer->blending == HWC_BLENDING_PREMULT)
1534        ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_BLEND_FG_PREMULT);
1535
1536    PipeArgs parg(mdpFlags, whf, z, isFg, static_cast<eRotFlags>(0),
1537                  layer->planeAlpha,
1538                  (ovutils::eBlending) getBlending(layer->blending));
1539
1540    // Configure MDP pipe for Color layer
1541    Dim pos(dst.left, dst.top, dst_w, dst_h);
1542    ctx->mOverlay->setSource(parg, dest);
1543    ctx->mOverlay->setColor(color, dest);
1544    ctx->mOverlay->setTransform(0, dest);
1545    ctx->mOverlay->setCrop(pos, dest);
1546    ctx->mOverlay->setPosition(pos, dest);
1547
1548    if (!ctx->mOverlay->commit(dest)) {
1549        ALOGE("%s: Configure color layer failed!", __FUNCTION__);
1550        return -1;
1551    }
1552    return 0;
1553}
1554
1555void updateSource(eTransform& orient, Whf& whf,
1556        hwc_rect_t& crop) {
1557    Dim srcCrop(crop.left, crop.top,
1558            crop.right - crop.left,
1559            crop.bottom - crop.top);
1560    orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
1561    preRotateSource(orient, whf, srcCrop);
1562    if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
1563        qdutils::MDSS_V5) {
1564        // Source for overlay will be the cropped (and rotated)
1565        crop.left = 0;
1566        crop.top = 0;
1567        crop.right = srcCrop.w;
1568        crop.bottom = srcCrop.h;
1569        // Set width & height equal to sourceCrop w & h
1570        whf.w = srcCrop.w;
1571        whf.h = srcCrop.h;
1572    } else {
1573        crop.left = srcCrop.x;
1574        crop.top = srcCrop.y;
1575        crop.right = srcCrop.x + srcCrop.w;
1576        crop.bottom = srcCrop.y + srcCrop.h;
1577    }
1578}
1579
1580int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
1581        const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
1582        eIsFg& isFg, const eDest& dest, Rotator **rot) {
1583
1584    private_handle_t *hnd = (private_handle_t *)layer->handle;
1585
1586    if(!hnd) {
1587        if (layer->flags & HWC_COLOR_FILL) {
1588            // Configure Color layer
1589            return configColorLayer(ctx, layer, dpy, mdpFlags, z, isFg, dest);
1590        }
1591        ALOGE("%s: layer handle is NULL", __FUNCTION__);
1592        return -1;
1593    }
1594
1595    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
1596
1597    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
1598    hwc_rect_t dst = layer->displayFrame;
1599    int transform = layer->transform;
1600    eTransform orient = static_cast<eTransform>(transform);
1601    int downscale = 0;
1602    int rotFlags = ovutils::ROT_FLAGS_NONE;
1603    uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
1604    Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
1605
1606    // Handle R/B swap
1607    if (layer->flags & HWC_FORMAT_RB_SWAP) {
1608        if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
1609            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
1610        else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
1611            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
1612    }
1613
1614    calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
1615
1616    if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 &&
1617       ctx->mMDP.version < qdutils::MDSS_V5) {
1618        downscale =  getDownscaleFactor(
1619            crop.right - crop.left,
1620            crop.bottom - crop.top,
1621            dst.right - dst.left,
1622            dst.bottom - dst.top);
1623        if(downscale) {
1624            rotFlags = ROT_DOWNSCALE_ENABLED;
1625        }
1626    }
1627
1628    setMdpFlags(layer, mdpFlags, downscale, transform);
1629
1630    if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
1631            ((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
1632        *rot = ctx->mRotMgr->getNext();
1633        if(*rot == NULL) return -1;
1634        ctx->mLayerRotMap[dpy]->add(layer, *rot);
1635        if(!dpy)
1636            BwcPM::setBwc(crop, dst, transform, mdpFlags);
1637        //Configure rotator for pre-rotation
1638        if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
1639            ALOGE("%s: configRotator failed!", __FUNCTION__);
1640            return -1;
1641        }
1642        whf.format = (*rot)->getDstFormat();
1643        updateSource(orient, whf, crop);
1644        rotFlags |= ovutils::ROT_PREROTATED;
1645    }
1646
1647    //For the mdp, since either we are pre-rotating or MDP does flips
1648    orient = OVERLAY_TRANSFORM_0;
1649    transform = 0;
1650    PipeArgs parg(mdpFlags, whf, z, isFg,
1651                  static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
1652                  (ovutils::eBlending) getBlending(layer->blending));
1653
1654    if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
1655        ALOGE("%s: commit failed for low res panel", __FUNCTION__);
1656        return -1;
1657    }
1658    return 0;
1659}
1660
1661//Helper to 1) Ensure crops dont have gaps 2) Ensure L and W are even
1662void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,
1663        private_handle_t *hnd) {
1664    if(cropL.right - cropL.left) {
1665        if(isYuvBuffer(hnd)) {
1666            //Always safe to even down left
1667            ovutils::even_floor(cropL.left);
1668            //If right is even, automatically width is even, since left is
1669            //already even
1670            ovutils::even_floor(cropL.right);
1671        }
1672        //Make sure there are no gaps between left and right splits if the layer
1673        //is spread across BOTH halves
1674        if(cropR.right - cropR.left) {
1675            cropR.left = cropL.right;
1676        }
1677    }
1678
1679    if(cropR.right - cropR.left) {
1680        if(isYuvBuffer(hnd)) {
1681            //Always safe to even down left
1682            ovutils::even_floor(cropR.left);
1683            //If right is even, automatically width is even, since left is
1684            //already even
1685            ovutils::even_floor(cropR.right);
1686        }
1687    }
1688}
1689
1690int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
1691        const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
1692        eIsFg& isFg, const eDest& lDest, const eDest& rDest,
1693        Rotator **rot) {
1694    private_handle_t *hnd = (private_handle_t *)layer->handle;
1695    if(!hnd) {
1696        ALOGE("%s: layer handle is NULL", __FUNCTION__);
1697        return -1;
1698    }
1699
1700    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
1701
1702    int hw_w = ctx->dpyAttr[dpy].xres;
1703    int hw_h = ctx->dpyAttr[dpy].yres;
1704    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
1705    hwc_rect_t dst = layer->displayFrame;
1706    int transform = layer->transform;
1707    eTransform orient = static_cast<eTransform>(transform);
1708    const int downscale = 0;
1709    int rotFlags = ROT_FLAGS_NONE;
1710    uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
1711    Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
1712
1713    // Handle R/B swap
1714    if (layer->flags & HWC_FORMAT_RB_SWAP) {
1715        if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
1716            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
1717        else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
1718            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
1719    }
1720
1721    /* Calculate the external display position based on MDP downscale,
1722       ActionSafe, and extorientation features. */
1723    calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
1724
1725    setMdpFlags(layer, mdpFlagsL, 0, transform);
1726
1727    if(lDest != OV_INVALID && rDest != OV_INVALID) {
1728        //Enable overfetch
1729        setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
1730    }
1731
1732    //Will do something only if feature enabled and conditions suitable
1733    //hollow call otherwise
1734    if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
1735        overlay::Writeback *wb = overlay::Writeback::getInstance();
1736        whf.format = wb->getOutputFormat();
1737    }
1738
1739    if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
1740        (*rot) = ctx->mRotMgr->getNext();
1741        if((*rot) == NULL) return -1;
1742        ctx->mLayerRotMap[dpy]->add(layer, *rot);
1743        //Configure rotator for pre-rotation
1744        if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
1745            ALOGE("%s: configRotator failed!", __FUNCTION__);
1746            return -1;
1747        }
1748        whf.format = (*rot)->getDstFormat();
1749        updateSource(orient, whf, crop);
1750        rotFlags |= ROT_PREROTATED;
1751    }
1752
1753    eMdpFlags mdpFlagsR = mdpFlagsL;
1754    setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER);
1755
1756    hwc_rect_t tmp_cropL = {0}, tmp_dstL = {0};
1757    hwc_rect_t tmp_cropR = {0}, tmp_dstR = {0};
1758
1759    const int lSplit = getLeftSplit(ctx, dpy);
1760
1761    if(lDest != OV_INVALID) {
1762        tmp_cropL = crop;
1763        tmp_dstL = dst;
1764        hwc_rect_t scissor = {0, 0, lSplit, hw_h };
1765        scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
1766        qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
1767    }
1768    if(rDest != OV_INVALID) {
1769        tmp_cropR = crop;
1770        tmp_dstR = dst;
1771        hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
1772        scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
1773        qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
1774    }
1775
1776    sanitizeSourceCrop(tmp_cropL, tmp_cropR, hnd);
1777
1778    //When buffer is H-flipped, contents of mixer config also needs to swapped
1779    //Not needed if the layer is confined to one half of the screen.
1780    //If rotator has been used then it has also done the flips, so ignore them.
1781    if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
1782            && rDest != OV_INVALID && (*rot) == NULL) {
1783        hwc_rect_t new_cropR;
1784        new_cropR.left = tmp_cropL.left;
1785        new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
1786
1787        hwc_rect_t new_cropL;
1788        new_cropL.left  = new_cropR.right;
1789        new_cropL.right = tmp_cropR.right;
1790
1791        tmp_cropL.left =  new_cropL.left;
1792        tmp_cropL.right =  new_cropL.right;
1793
1794        tmp_cropR.left = new_cropR.left;
1795        tmp_cropR.right =  new_cropR.right;
1796
1797    }
1798
1799    //For the mdp, since either we are pre-rotating or MDP does flips
1800    orient = OVERLAY_TRANSFORM_0;
1801    transform = 0;
1802
1803    //configure left mixer
1804    if(lDest != OV_INVALID) {
1805        PipeArgs pargL(mdpFlagsL, whf, z, isFg,
1806                       static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
1807                       (ovutils::eBlending) getBlending(layer->blending));
1808
1809        if(configMdp(ctx->mOverlay, pargL, orient,
1810                tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
1811            ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
1812            return -1;
1813        }
1814    }
1815
1816    //configure right mixer
1817    if(rDest != OV_INVALID) {
1818        PipeArgs pargR(mdpFlagsR, whf, z, isFg,
1819                       static_cast<eRotFlags>(rotFlags),
1820                       layer->planeAlpha,
1821                       (ovutils::eBlending) getBlending(layer->blending));
1822        tmp_dstR.right = tmp_dstR.right - lSplit;
1823        tmp_dstR.left = tmp_dstR.left - lSplit;
1824        if(configMdp(ctx->mOverlay, pargR, orient,
1825                tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
1826            ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
1827            return -1;
1828        }
1829    }
1830
1831    return 0;
1832}
1833
1834int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
1835        const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
1836        eIsFg& isFg, const eDest& lDest, const eDest& rDest,
1837        Rotator **rot) {
1838    private_handle_t *hnd = (private_handle_t *)layer->handle;
1839    if(!hnd) {
1840        ALOGE("%s: layer handle is NULL", __FUNCTION__);
1841        return -1;
1842    }
1843
1844    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
1845
1846    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);;
1847    hwc_rect_t dst = layer->displayFrame;
1848    int transform = layer->transform;
1849    eTransform orient = static_cast<eTransform>(transform);
1850    const int downscale = 0;
1851    int rotFlags = ROT_FLAGS_NONE;
1852    //Splitting only YUV layer on primary panel needs different zorders
1853    //for both layers as both the layers are configured to single mixer
1854    eZorder lz = z;
1855    eZorder rz = (eZorder)(z + 1);
1856
1857    Whf whf(getWidth(hnd), getHeight(hnd),
1858            getMdpFormat(hnd->format), hnd->size);
1859
1860    /* Calculate the external display position based on MDP downscale,
1861       ActionSafe, and extorientation features. */
1862    calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
1863
1864    setMdpFlags(layer, mdpFlagsL, 0, transform);
1865    trimLayer(ctx, dpy, transform, crop, dst);
1866
1867    if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
1868        (*rot) = ctx->mRotMgr->getNext();
1869        if((*rot) == NULL) return -1;
1870        ctx->mLayerRotMap[dpy]->add(layer, *rot);
1871        if(!dpy)
1872            BwcPM::setBwc(crop, dst, transform, mdpFlagsL);
1873        //Configure rotator for pre-rotation
1874        if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
1875            ALOGE("%s: configRotator failed!", __FUNCTION__);
1876            return -1;
1877        }
1878        whf.format = (*rot)->getDstFormat();
1879        updateSource(orient, whf, crop);
1880        rotFlags |= ROT_PREROTATED;
1881    }
1882
1883    eMdpFlags mdpFlagsR = mdpFlagsL;
1884    int lSplit = dst.left + (dst.right - dst.left)/2;
1885
1886    hwc_rect_t tmp_cropL = {0}, tmp_dstL = {0};
1887    hwc_rect_t tmp_cropR = {0}, tmp_dstR = {0};
1888
1889    if(lDest != OV_INVALID) {
1890        tmp_cropL = crop;
1891        tmp_dstL = dst;
1892        hwc_rect_t scissor = {dst.left, dst.top, lSplit, dst.bottom };
1893        qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
1894    }
1895    if(rDest != OV_INVALID) {
1896        tmp_cropR = crop;
1897        tmp_dstR = dst;
1898        hwc_rect_t scissor = {lSplit, dst.top, dst.right, dst.bottom };
1899        qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
1900    }
1901
1902    sanitizeSourceCrop(tmp_cropL, tmp_cropR, hnd);
1903
1904    //When buffer is H-flipped, contents of mixer config also needs to swapped
1905    //Not needed if the layer is confined to one half of the screen.
1906    //If rotator has been used then it has also done the flips, so ignore them.
1907    if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
1908            && rDest != OV_INVALID && (*rot) == NULL) {
1909        hwc_rect_t new_cropR;
1910        new_cropR.left = tmp_cropL.left;
1911        new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
1912
1913        hwc_rect_t new_cropL;
1914        new_cropL.left  = new_cropR.right;
1915        new_cropL.right = tmp_cropR.right;
1916
1917        tmp_cropL.left =  new_cropL.left;
1918        tmp_cropL.right =  new_cropL.right;
1919
1920        tmp_cropR.left = new_cropR.left;
1921        tmp_cropR.right =  new_cropR.right;
1922
1923    }
1924
1925    //For the mdp, since either we are pre-rotating or MDP does flips
1926    orient = OVERLAY_TRANSFORM_0;
1927    transform = 0;
1928
1929    //configure left half
1930    if(lDest != OV_INVALID) {
1931        PipeArgs pargL(mdpFlagsL, whf, lz, isFg,
1932                static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
1933                (ovutils::eBlending) getBlending(layer->blending));
1934
1935        if(configMdp(ctx->mOverlay, pargL, orient,
1936                    tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
1937            ALOGE("%s: commit failed for left half config", __FUNCTION__);
1938            return -1;
1939        }
1940    }
1941
1942    //configure right half
1943    if(rDest != OV_INVALID) {
1944        PipeArgs pargR(mdpFlagsR, whf, rz, isFg,
1945                static_cast<eRotFlags>(rotFlags),
1946                layer->planeAlpha,
1947                (ovutils::eBlending) getBlending(layer->blending));
1948        if(configMdp(ctx->mOverlay, pargR, orient,
1949                    tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
1950            ALOGE("%s: commit failed for right half config", __FUNCTION__);
1951            return -1;
1952        }
1953    }
1954
1955    return 0;
1956}
1957
1958bool canUseRotator(hwc_context_t *ctx, int dpy) {
1959    if(qdutils::MDPVersion::getInstance().is8x26() &&
1960            isSecondaryConnected(ctx) &&
1961            !ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) {
1962        /* 8x26 mdss driver supports multiplexing of DMA pipe
1963         * in LINE and BLOCK modes for writeback panels.
1964         */
1965        if(dpy == HWC_DISPLAY_PRIMARY)
1966            return false;
1967    }
1968    if(ctx->mMDP.version == qdutils::MDP_V3_0_4)
1969        return false;
1970    return true;
1971}
1972
1973int getLeftSplit(hwc_context_t *ctx, const int& dpy) {
1974    //Default even split for all displays with high res
1975    int lSplit = ctx->dpyAttr[dpy].xres / 2;
1976    if(dpy == HWC_DISPLAY_PRIMARY &&
1977            qdutils::MDPVersion::getInstance().getLeftSplit()) {
1978        //Override if split published by driver for primary
1979        lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
1980    }
1981    return lSplit;
1982}
1983
1984bool isDisplaySplit(hwc_context_t* ctx, int dpy) {
1985    if(ctx->dpyAttr[dpy].xres > qdutils::MAX_DISPLAY_DIM) {
1986        return true;
1987    }
1988    //For testing we could split primary via device tree values
1989    if(dpy == HWC_DISPLAY_PRIMARY &&
1990        qdutils::MDPVersion::getInstance().getRightSplit()) {
1991        return true;
1992    }
1993    return false;
1994}
1995
1996//clear prev layer prop flags and realloc for current frame
1997void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers) {
1998    if(ctx->layerProp[dpy]) {
1999       delete[] ctx->layerProp[dpy];
2000       ctx->layerProp[dpy] = NULL;
2001    }
2002    ctx->layerProp[dpy] = new LayerProp[numAppLayers];
2003}
2004
2005/* Since we fake non-Hybrid WFD solution as external display, this
2006 * function helps us in determining the priority between external
2007 * (hdmi/non-Hybrid WFD display) and virtual display devices(SSD/
2008 * screenrecord). This can be removed once wfd-client migrates to
2009 * using virtual-display api's.
2010 */
2011bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
2012                                const hwc_display_contents_1_t *list) {
2013
2014    /* We rely on the fact that for pure virtual display solution
2015     * list->outbuf will be a non-NULL handle.
2016     *
2017     * If there are three active displays (which means there is one
2018     * primary, one external and one virtual active display)
2019     * we give mdss/mdp hw resources(pipes,smp,etc) for external
2020     * display(hdmi/non-Hybrid WFD display) rather than for virtual
2021     * display(SSD/screenrecord)
2022     */
2023
2024    if(list->outbuf and (ctx->numActiveDisplays == HWC_NUM_DISPLAY_TYPES)) {
2025        return false;
2026    }
2027
2028    return true;
2029}
2030
2031bool isGLESComp(hwc_context_t *ctx,
2032                     hwc_display_contents_1_t* list) {
2033    int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
2034    for(int index = 0; index < numAppLayers; index++) {
2035        hwc_layer_1_t* layer = &(list->hwLayers[index]);
2036        if(layer->compositionType == HWC_FRAMEBUFFER)
2037            return true;
2038    }
2039    return false;
2040}
2041
2042void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
2043    struct gpu_hint_info *gpuHint = &ctx->mGPUHintInfo;
2044    if(!gpuHint->mGpuPerfModeEnable)
2045        return;
2046    /* Set the GPU hint flag to high for MIXED/GPU composition only for
2047       first frame after MDP -> GPU/MIXED mode transition. Set the GPU
2048       hint to default if the previous composition is GPU or current GPU
2049       composition is due to idle fallback */
2050    if(!gpuHint->mEGLDisplay || !gpuHint->mEGLContext) {
2051        gpuHint->mEGLDisplay = eglGetCurrentDisplay();
2052        if(!gpuHint->mEGLDisplay) {
2053            ALOGW("%s Warning: EGL current display is NULL", __FUNCTION__);
2054            return;
2055        }
2056        gpuHint->mEGLContext = eglGetCurrentContext();
2057        if(!gpuHint->mEGLContext) {
2058            ALOGW("%s Warning: EGL current context is NULL", __FUNCTION__);
2059            return;
2060        }
2061    }
2062    if(isGLESComp(ctx, list)) {
2063        if(!gpuHint->mPrevCompositionGLES && !MDPComp::isIdleFallback()) {
2064            EGLint attr_list[] = {EGL_GPU_HINT_1,
2065                                  EGL_GPU_LEVEL_3,
2066                                  EGL_NONE };
2067            if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_3) &&
2068                !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
2069                                    gpuHint->mEGLContext, attr_list)) {
2070                ALOGW("eglGpuPerfHintQCOM failed for Built in display");
2071            } else {
2072                gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_3;
2073                gpuHint->mPrevCompositionGLES = true;
2074            }
2075        } else {
2076            EGLint attr_list[] = {EGL_GPU_HINT_1,
2077                                  EGL_GPU_LEVEL_0,
2078                                  EGL_NONE };
2079            if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
2080                !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
2081                                    gpuHint->mEGLContext, attr_list)) {
2082                ALOGW("eglGpuPerfHintQCOM failed for Built in display");
2083            } else {
2084                gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
2085            }
2086        }
2087    } else {
2088        /* set the GPU hint flag to default for MDP composition */
2089        EGLint attr_list[] = {EGL_GPU_HINT_1,
2090                              EGL_GPU_LEVEL_0,
2091                              EGL_NONE };
2092        if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
2093                !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
2094                                    gpuHint->mEGLContext, attr_list)) {
2095            ALOGW("eglGpuPerfHintQCOM failed for Built in display");
2096        } else {
2097            gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
2098        }
2099        gpuHint->mPrevCompositionGLES = false;
2100    }
2101}
2102
2103void BwcPM::setBwc(const hwc_rect_t& crop,
2104            const hwc_rect_t& dst, const int& transform,
2105            ovutils::eMdpFlags& mdpFlags) {
2106    //Target doesnt support Bwc
2107    if(!qdutils::MDPVersion::getInstance().supportsBWC()) {
2108        return;
2109    }
2110    //src width > MAX mixer supported dim
2111    if((crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
2112        return;
2113    }
2114    //Decimation necessary, cannot use BWC. H/W requirement.
2115    if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
2116        int src_w = crop.right - crop.left;
2117        int src_h = crop.bottom - crop.top;
2118        int dst_w = dst.right - dst.left;
2119        int dst_h = dst.bottom - dst.top;
2120        if(transform & HAL_TRANSFORM_ROT_90) {
2121            swap(src_w, src_h);
2122        }
2123        float horDscale = 0.0f;
2124        float verDscale = 0.0f;
2125        int horzDeci = 0;
2126        int vertDeci = 0;
2127        ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horDscale,
2128                verDscale);
2129        //TODO Use log2f once math.h has it
2130        if((int)horDscale)
2131            horzDeci = (int)(log(horDscale) / log(2));
2132        if((int)verDscale)
2133            vertDeci = (int)(log(verDscale) / log(2));
2134        if(horzDeci || vertDeci) return;
2135    }
2136    //Property
2137    char value[PROPERTY_VALUE_MAX];
2138    property_get("debug.disable.bwc", value, "0");
2139     if(atoi(value)) return;
2140
2141    ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDSS_MDP_BWC_EN);
2142}
2143
2144void LayerRotMap::add(hwc_layer_1_t* layer, Rotator *rot) {
2145    if(mCount >= MAX_SESS) return;
2146    mLayer[mCount] = layer;
2147    mRot[mCount] = rot;
2148    mCount++;
2149}
2150
2151void LayerRotMap::reset() {
2152    for (int i = 0; i < MAX_SESS; i++) {
2153        mLayer[i] = 0;
2154        mRot[i] = 0;
2155    }
2156    mCount = 0;
2157}
2158
2159void LayerRotMap::clear() {
2160    RotMgr::getInstance()->markUnusedTop(mCount);
2161    reset();
2162}
2163
2164void LayerRotMap::setReleaseFd(const int& fence) {
2165    for(uint32_t i = 0; i < mCount; i++) {
2166        mRot[i]->setReleaseFd(dup(fence));
2167    }
2168}
2169
2170};//namespace qhwc
2171