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