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