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