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