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