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