hwc.cpp revision e5fd024417b93aa52eb9050131242779d8295a07
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#include <fcntl.h> 22#include <errno.h> 23 24#include <cutils/log.h> 25#include <cutils/atomic.h> 26#include <EGL/egl.h> 27#include <utils/Trace.h> 28#include <sys/ioctl.h> 29#include <overlay.h> 30#include <overlayRotator.h> 31#include <overlayWriteback.h> 32#include <mdp_version.h> 33#include "hwc_utils.h" 34#include "hwc_fbupdate.h" 35#include "hwc_mdpcomp.h" 36#include "hwc_dump_layers.h" 37#include "external.h" 38#include "hwc_copybit.h" 39#include "hwc_ad.h" 40#include "profiler.h" 41#include "hwc_virtual.h" 42 43using namespace qhwc; 44using namespace overlay; 45 46#define VSYNC_DEBUG 0 47#define BLANK_DEBUG 1 48 49static int hwc_device_open(const struct hw_module_t* module, 50 const char* name, 51 struct hw_device_t** device); 52 53static struct hw_module_methods_t hwc_module_methods = { 54 open: hwc_device_open 55}; 56 57static void reset_panel(struct hwc_composer_device_1* dev); 58 59hwc_module_t HAL_MODULE_INFO_SYM = { 60 common: { 61 tag: HARDWARE_MODULE_TAG, 62 version_major: 2, 63 version_minor: 0, 64 id: HWC_HARDWARE_MODULE_ID, 65 name: "Qualcomm Hardware Composer Module", 66 author: "CodeAurora Forum", 67 methods: &hwc_module_methods, 68 dso: 0, 69 reserved: {0}, 70 } 71}; 72 73/* In case of non-hybrid WFD session, we are fooling SF by piggybacking on 74 * HDMI display ID for virtual. This helper is needed to differentiate their 75 * paths in HAL. 76 * TODO: Not needed once we have WFD client working on top of Google API's */ 77 78static int getDpyforExternalDisplay(hwc_context_t *ctx, int dpy) { 79 if(dpy == HWC_DISPLAY_EXTERNAL && ctx->mVirtualonExtActive) 80 return HWC_DISPLAY_VIRTUAL; 81 return dpy; 82} 83 84/* 85 * Save callback functions registered to HWC 86 */ 87static void hwc_registerProcs(struct hwc_composer_device_1* dev, 88 hwc_procs_t const* procs) 89{ 90 ALOGI("%s", __FUNCTION__); 91 hwc_context_t* ctx = (hwc_context_t*)(dev); 92 if(!ctx) { 93 ALOGE("%s: Invalid context", __FUNCTION__); 94 return; 95 } 96 ctx->proc = procs; 97 98 // Now that we have the functions needed, kick off 99 // the uevent & vsync threads 100 init_uevent_thread(ctx); 101 init_vsync_thread(ctx); 102} 103 104static void setPaddingRound(hwc_context_t *ctx, int numDisplays, 105 hwc_display_contents_1_t** displays) { 106 ctx->isPaddingRound = false; 107 for(int i = 0; i < numDisplays; i++) { 108 hwc_display_contents_1_t *list = displays[i]; 109 if (LIKELY(list && list->numHwLayers > 0)) { 110 if((ctx->mPrevHwLayerCount[i] == 1 or 111 ctx->mPrevHwLayerCount[i] == 0) and 112 (list->numHwLayers > 1)) { 113 /* If the previous cycle for dpy 'i' has 0 AppLayers and the 114 * current cycle has atleast 1 AppLayer, padding round needs 115 * to be invoked in current cycle on all the active displays 116 * to free up the resources. 117 */ 118 ctx->isPaddingRound = true; 119 } 120 ctx->mPrevHwLayerCount[i] = (int)list->numHwLayers; 121 } else { 122 ctx->mPrevHwLayerCount[i] = 0; 123 } 124 } 125} 126 127/* Based on certain conditions, isPaddingRound will be set 128 * to make this function self-contained */ 129static void setDMAState(hwc_context_t *ctx, int numDisplays, 130 hwc_display_contents_1_t** displays) { 131 132 if(ctx->mRotMgr->getNumActiveSessions() == 0) 133 Overlay::setDMAMode(Overlay::DMA_LINE_MODE); 134 135 for(int i = 0; i < numDisplays; i++) { 136 hwc_display_contents_1_t *list = displays[i]; 137 if (LIKELY(list && list->numHwLayers > 0)) { 138 for(size_t j = 0; j < list->numHwLayers; j++) { 139 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET) 140 { 141 hwc_layer_1_t const* layer = &list->hwLayers[i]; 142 private_handle_t *hnd = (private_handle_t *)layer->handle; 143 144 /* If a video layer requires rotation, set the DMA state 145 * to BLOCK_MODE */ 146 147 if (UNLIKELY(isYuvBuffer(hnd)) && canUseRotator(ctx,i) && 148 (layer->transform & HWC_TRANSFORM_ROT_90)) { 149 if(not qdutils::MDPVersion::getInstance().is8x26()) { 150 if(ctx->mOverlay->isPipeTypeAttached( 151 overlay::utils::OV_MDP_PIPE_DMA)) 152 ctx->isPaddingRound = true; 153 } 154 Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE); 155 } 156 } 157 } 158 if(i) { 159 /* Uncomment the below code for testing purpose. 160 Assuming the orientation value is in terms of HAL_TRANSFORM, 161 this needs mapping to HAL, if its in different convention */ 162 163 /* char value[PROPERTY_VALUE_MAX]; 164 property_get("sys.ext_orientation", value, "0"); 165 ctx->mExtOrientation = atoi(value);*/ 166 167 if(ctx->mExtOrientation || ctx->mBufferMirrorMode) { 168 if(ctx->mOverlay->isPipeTypeAttached( 169 overlay::utils::OV_MDP_PIPE_DMA)) { 170 ctx->isPaddingRound = true; 171 } 172 Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE); 173 } 174 } 175 } 176 } 177} 178 179static void setNumActiveDisplays(hwc_context_t *ctx, int numDisplays, 180 hwc_display_contents_1_t** displays) { 181 182 ctx->numActiveDisplays = 0; 183 for(int i = 0; i < numDisplays; i++) { 184 hwc_display_contents_1_t *list = displays[i]; 185 if (LIKELY(list && list->numHwLayers > 0)) { 186 /* For display devices like SSD and screenrecord, we cannot 187 * rely on isActive and connected attributes of dpyAttr to 188 * determine if the displaydevice is active. Hence in case if 189 * the layer-list is non-null and numHwLayers > 0, we assume 190 * the display device to be active. 191 */ 192 ctx->numActiveDisplays += 1; 193 } 194 } 195} 196 197static void reset(hwc_context_t *ctx, int numDisplays, 198 hwc_display_contents_1_t** displays) { 199 200 201 for(int i = 0; i < numDisplays; i++) { 202 hwc_display_contents_1_t *list = displays[i]; 203 // XXX:SurfaceFlinger no longer guarantees that this 204 // value is reset on every prepare. However, for the layer 205 // cache we need to reset it. 206 // We can probably rethink that later on 207 if (LIKELY(list && list->numHwLayers > 0)) { 208 for(size_t j = 0; j < list->numHwLayers; j++) { 209 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET) 210 list->hwLayers[j].compositionType = HWC_FRAMEBUFFER; 211 } 212 213 } 214 215 if(ctx->mFBUpdate[i]) 216 ctx->mFBUpdate[i]->reset(); 217 if(ctx->mCopyBit[i]) 218 ctx->mCopyBit[i]->reset(); 219 if(ctx->mLayerRotMap[i]) 220 ctx->mLayerRotMap[i]->reset(); 221 } 222 223 ctx->mAD->reset(); 224 MDPComp::reset(); 225 if(ctx->mHWCVirtual) 226 ctx->mHWCVirtual->destroy(ctx, numDisplays, displays); 227} 228 229bool isEqual(float f1, float f2) { 230 return ((int)(f1*100) == (int)(f2*100)) ? true : false; 231} 232 233static void scaleDisplayFrame(hwc_context_t *ctx, int dpy, 234 hwc_display_contents_1_t *list) { 235 uint32_t origXres = ctx->dpyAttr[dpy].xres_orig; 236 uint32_t origYres = ctx->dpyAttr[dpy].yres_orig; 237 uint32_t fakeXres = ctx->dpyAttr[dpy].xres; 238 uint32_t fakeYres = ctx->dpyAttr[dpy].yres; 239 float xresRatio = (float)origXres / (float)fakeXres; 240 float yresRatio = (float)origYres / (float)fakeYres; 241 for (size_t i = 0; i < list->numHwLayers; i++) { 242 hwc_layer_1_t *layer = &list->hwLayers[i]; 243 hwc_rect_t& displayFrame = layer->displayFrame; 244 hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf); 245 uint32_t layerWidth = displayFrame.right - displayFrame.left; 246 uint32_t layerHeight = displayFrame.bottom - displayFrame.top; 247 uint32_t sourceWidth = sourceCrop.right - sourceCrop.left; 248 uint32_t sourceHeight = sourceCrop.bottom - sourceCrop.top; 249 250 if (isEqual(((float)layerWidth / (float)sourceWidth), xresRatio) && 251 isEqual(((float)layerHeight / (float)sourceHeight), yresRatio)) 252 break; 253 254 displayFrame.left = (int)(xresRatio * (float)displayFrame.left); 255 displayFrame.top = (int)(yresRatio * (float)displayFrame.top); 256 displayFrame.right = (int)((float)displayFrame.left + 257 (float)layerWidth * xresRatio); 258 displayFrame.bottom = (int)((float)displayFrame.top + 259 (float)layerHeight * yresRatio); 260 } 261} 262 263static bool optimizePrepare(hwc_context_t *ctx, int numDisplays, 264 hwc_display_contents_1_t** displays) { 265 266 /* Do not re-program H/W, if frame geometry has not changed. 267 * But honor these exceptions: 268 * 1. Padding round 269 * 2. Idle fallback 270 * 3. Overlay is not configured 271 * 4. External/Virtual display is in Configure state 272 * 5. External/Virtual is Paused OR not connected/active 273 * 6. Non-Overlay device 274 */ 275 276 if (ctx->isPaddingRound || MDPComp::isIdleFallback() || 277 !ctx->mOverlay->isConfigured() || isSecondaryConfiguring(ctx) || 278 ctx->mMDP.version < qdutils::MDP_V4_0) { 279 return false; 280 } 281 282 bool isOptimized = false; 283 for (uint32_t i = 0; i < numDisplays; i++) { 284 hwc_display_contents_1_t *list = displays[i]; 285 286 if (list) { 287 if (list->flags & HWC_GEOMETRY_CHANGED) { 288 return false; 289 } 290 int dpy = getDpyforExternalDisplay(ctx, i); 291 if (dpy && (ctx->dpyAttr[dpy].isPause || 292 !ctx->dpyAttr[dpy].connected || 293 !ctx->dpyAttr[dpy].isActive)) { 294 return false; 295 } 296 // Set layer composition type as per last frame 297 ctx->mMDPComp[dpy]->setMDPCompLayerFlags(ctx, list); 298 isOptimized = true; 299 } 300 } 301 302 return isOptimized; 303} 304 305static int hwc_prepare_primary(hwc_composer_device_1 *dev, 306 hwc_display_contents_1_t *list) { 307 ATRACE_CALL(); 308 hwc_context_t* ctx = (hwc_context_t*)(dev); 309 const int dpy = HWC_DISPLAY_PRIMARY; 310 bool fbComp = false; 311 if (LIKELY(list && list->numHwLayers > 1) && 312 ctx->dpyAttr[dpy].isActive) { 313 314 if (ctx->dpyAttr[dpy].customFBSize) 315 scaleDisplayFrame(ctx, dpy, list); 316 317 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1); 318 setListStats(ctx, list, dpy); 319 320 fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0); 321 322 if (fbComp) { 323 const int fbZ = 0; 324 ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ); 325 } 326 327 if (ctx->mMDP.version < qdutils::MDP_V4_0) { 328 if(ctx->mCopyBit[dpy]) 329 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy); 330 } 331 setGPUHint(ctx, list); 332 } 333 return 0; 334} 335 336static int hwc_prepare_external(hwc_composer_device_1 *dev, 337 hwc_display_contents_1_t *list) { 338 ATRACE_CALL(); 339 hwc_context_t* ctx = (hwc_context_t*)(dev); 340 const int dpy = HWC_DISPLAY_EXTERNAL; 341 342 if (LIKELY(list && list->numHwLayers > 1) && 343 ctx->dpyAttr[dpy].isActive && 344 ctx->dpyAttr[dpy].connected) { 345 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1); 346 if(!ctx->dpyAttr[dpy].isPause) { 347 ctx->dpyAttr[dpy].isConfiguring = false; 348 setListStats(ctx, list, dpy); 349 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) { 350 const int fbZ = 0; 351 ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ); 352 } 353 } else { 354 /* External Display is in Pause state. 355 * Mark all application layers as OVERLAY so that 356 * GPU will not compose. 357 */ 358 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) { 359 hwc_layer_1_t *layer = &list->hwLayers[i]; 360 layer->compositionType = HWC_OVERLAY; 361 } 362 } 363 } 364 return 0; 365} 366 367static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, 368 hwc_display_contents_1_t** displays) 369{ 370 int ret = 0; 371 hwc_context_t* ctx = (hwc_context_t*)(dev); 372 373 if (ctx->mPanelResetStatus) { 374 ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__); 375 reset_panel(dev); 376 } 377 378 //Will be unlocked at the end of set 379 ctx->mDrawLock.lock(); 380 setPaddingRound(ctx,numDisplays,displays); 381 setDMAState(ctx,numDisplays,displays); 382 setNumActiveDisplays(ctx,numDisplays,displays); 383 384 if (optimizePrepare(ctx, numDisplays, displays)) { 385 // Do not re-program H/W, if it is not needed 386 return ret; 387 } 388 389 reset(ctx, (int)numDisplays, displays); 390 391 ctx->mOverlay->configBegin(); 392 ctx->mRotMgr->configBegin(); 393 overlay::Writeback::configBegin(); 394 395 for (int32_t i = ((int32_t)numDisplays-1); i >=0 ; i--) { 396 hwc_display_contents_1_t *list = displays[i]; 397 int dpy = getDpyforExternalDisplay(ctx, i); 398 switch(dpy) { 399 case HWC_DISPLAY_PRIMARY: 400 ret = hwc_prepare_primary(dev, list); 401 break; 402 case HWC_DISPLAY_EXTERNAL: 403 ret = hwc_prepare_external(dev, list); 404 break; 405 case HWC_DISPLAY_VIRTUAL: 406 if(ctx->mHWCVirtual) 407 ret = ctx->mHWCVirtual->prepare(dev, list); 408 break; 409 default: 410 ret = -EINVAL; 411 } 412 } 413 414 ctx->mOverlay->configDone(); 415 ctx->mRotMgr->configDone(); 416 overlay::Writeback::configDone(); 417 418 return ret; 419} 420 421static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy, 422 int event, int enable) 423{ 424 ATRACE_CALL(); 425 int ret = 0; 426 hwc_context_t* ctx = (hwc_context_t*)(dev); 427 switch(event) { 428 case HWC_EVENT_VSYNC: 429 if (ctx->vstate.enable == enable) 430 break; 431 ret = hwc_vsync_control(ctx, dpy, enable); 432 if(ret == 0) 433 ctx->vstate.enable = !!enable; 434 ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s", 435 (enable)?"ENABLED":"DISABLED"); 436 break; 437#ifdef QCOM_BSP 438 case HWC_EVENT_ORIENTATION: 439 if(dpy == HWC_DISPLAY_PRIMARY) { 440 Locker::Autolock _l(ctx->mDrawLock); 441 // store the primary display orientation 442 ctx->deviceOrientation = enable; 443 } 444 break; 445#endif 446 default: 447 ret = -EINVAL; 448 } 449 return ret; 450} 451 452static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank) 453{ 454 ATRACE_CALL(); 455 hwc_context_t* ctx = (hwc_context_t*)(dev); 456 457 Locker::Autolock _l(ctx->mDrawLock); 458 int ret = 0, value = 0; 459 460 /* In case of non-hybrid WFD session, we are fooling SF by 461 * piggybacking on HDMI display ID for virtual. 462 * TODO: Not needed once we have WFD client working on top 463 * of Google API's. 464 */ 465 dpy = getDpyforExternalDisplay(ctx,dpy); 466 467 ALOGD_IF(BLANK_DEBUG, "%s: %s display: %d", __FUNCTION__, 468 blank==1 ? "Blanking":"Unblanking", dpy); 469 if(blank) { 470 // free up all the overlay pipes in use 471 // when we get a blank for either display 472 // makes sure that all pipes are freed 473 ctx->mOverlay->configBegin(); 474 ctx->mOverlay->configDone(); 475 ctx->mRotMgr->clear(); 476 // If VDS is connected, do not clear WB object as it 477 // will end up detaching IOMMU. This is required 478 // to send black frame to WFD sink on power suspend. 479 // Note: With this change, we keep the WriteBack object 480 // alive on power suspend for AD use case. 481 } 482 switch(dpy) { 483 case HWC_DISPLAY_PRIMARY: 484 value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK; 485 if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) { 486 ALOGE("%s: Failed to handle blank event(%d) for Primary!!", 487 __FUNCTION__, blank ); 488 return -1; 489 } 490 491 if(!blank) { 492 // Enable HPD here, as during bootup unblank is called 493 // when SF is completely initialized 494 ctx->mExtDisplay->setHPD(1); 495 } 496 497 ctx->dpyAttr[dpy].isActive = !blank; 498 499 if(ctx->mVirtualonExtActive) { 500 /* if mVirtualonExtActive is true, display hal will 501 * receive unblank calls for non-hybrid WFD solution 502 * since we piggyback on HDMI. 503 * TODO: Not needed once we have WFD client working on top 504 of Google API's */ 505 break; 506 } 507 case HWC_DISPLAY_VIRTUAL: 508 /* There are two ways to reach this block of code. 509 510 * Display hal has received unblank call on HWC_DISPLAY_EXTERNAL 511 and ctx->mVirtualonExtActive is true. In this case, non-hybrid 512 WFD is active. If so, getDpyforExternalDisplay will return dpy 513 as HWC_DISPLAY_VIRTUAL. 514 515 * Display hal has received unblank call on HWC_DISPLAY_PRIMARY 516 and since SF is not aware of VIRTUAL DISPLAY being handle by HWC, 517 it wont send blank / unblank events for it. We piggyback on 518 PRIMARY DISPLAY events to release mdp pipes and 519 activate/deactivate VIRTUAL DISPLAY. 520 521 * TODO: This separate case statement is not needed once we have 522 WFD client working on top of Google API's. 523 524 */ 525 526 if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) { 527 if(blank and (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause)) { 528 int dpy = HWC_DISPLAY_VIRTUAL; 529 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 530 ALOGE("%s: display commit fail for virtual!", __FUNCTION__); 531 ret = -1; 532 } 533 } 534 ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank; 535 } 536 break; 537 case HWC_DISPLAY_EXTERNAL: 538 if(blank) { 539 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 540 ALOGE("%s: display commit fail for external!", __FUNCTION__); 541 ret = -1; 542 } 543 } 544 ctx->dpyAttr[dpy].isActive = !blank; 545 break; 546 default: 547 return -EINVAL; 548 } 549 550 ALOGD_IF(BLANK_DEBUG, "%s: Done %s display: %d", __FUNCTION__, 551 blank ? "blanking":"unblanking", dpy); 552 return ret; 553} 554 555static void reset_panel(struct hwc_composer_device_1* dev) 556{ 557 int ret = 0; 558 hwc_context_t* ctx = (hwc_context_t*)(dev); 559 560 if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) { 561 ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__); 562 ctx->mPanelResetStatus = false; 563 return; 564 } 565 566 ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__); 567 ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1); 568 if (ret < 0) { 569 ALOGE("%s: FBIOBLANK failed to BLANK: %s", __FUNCTION__, 570 strerror(errno)); 571 } 572 573 ALOGD("%s: calling UNBLANK DISPLAY and enabling vsync", __FUNCTION__); 574 ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 0); 575 if (ret < 0) { 576 ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__, 577 strerror(errno)); 578 } 579 hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1); 580 581 ctx->mPanelResetStatus = false; 582} 583 584 585static int hwc_query(struct hwc_composer_device_1* dev, 586 int param, int* value) 587{ 588 hwc_context_t* ctx = (hwc_context_t*)(dev); 589 int supported = HWC_DISPLAY_PRIMARY_BIT; 590 591 switch (param) { 592 case HWC_BACKGROUND_LAYER_SUPPORTED: 593 // Not supported for now 594 value[0] = 0; 595 break; 596 case HWC_DISPLAY_TYPES_SUPPORTED: 597 if(ctx->mMDP.hasOverlay) { 598 supported |= HWC_DISPLAY_VIRTUAL_BIT; 599 if(!(qdutils::MDPVersion::getInstance().is8x26() || 600 qdutils::MDPVersion::getInstance().is8x16())) 601 supported |= HWC_DISPLAY_EXTERNAL_BIT; 602 } 603 value[0] = supported; 604 break; 605 case HWC_FORMAT_RB_SWAP: 606 value[0] = 1; 607 break; 608 case HWC_COLOR_FILL: 609 value[0] = 1; 610 break; 611 default: 612 return -EINVAL; 613 } 614 return 0; 615 616} 617 618 619static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 620 ATRACE_CALL(); 621 int ret = 0; 622 const int dpy = HWC_DISPLAY_PRIMARY; 623 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) { 624 size_t last = list->numHwLayers - 1; 625 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 626 int fd = -1; //FenceFD from the Copybit(valid in async mode) 627 bool copybitDone = false; 628 if(ctx->mCopyBit[dpy]) 629 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); 630 if(list->numHwLayers > 1) 631 hwc_sync(ctx, list, dpy, fd); 632 633 // Dump the layers for primary 634 if(ctx->mHwcDebug[dpy]) 635 ctx->mHwcDebug[dpy]->dumpLayers(list); 636 637 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { 638 ALOGE("%s: MDPComp draw failed", __FUNCTION__); 639 ret = -1; 640 } 641 642 //TODO We dont check for SKIP flag on this layer because we need PAN 643 //always. Last layer is always FB 644 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 645 if(copybitDone && ctx->mMDP.version >= qdutils::MDP_V4_0) { 646 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer(); 647 } 648 649 if(hnd) { 650 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { 651 ALOGE("%s: FBUpdate draw failed", __FUNCTION__); 652 ret = -1; 653 } 654 } 655 656 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, 657 ctx->listStats[dpy].roi)) { 658 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); 659 ret = -1; 660 } 661 662 } 663 664 closeAcquireFds(list); 665 return ret; 666} 667 668static int hwc_set_external(hwc_context_t *ctx, 669 hwc_display_contents_1_t* list) 670{ 671 ATRACE_CALL(); 672 int ret = 0; 673 674 const int dpy = HWC_DISPLAY_EXTERNAL; 675 676 677 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive && 678 ctx->dpyAttr[dpy].connected && 679 !ctx->dpyAttr[dpy].isPause) { 680 size_t last = list->numHwLayers - 1; 681 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 682 int fd = -1; //FenceFD from the Copybit(valid in async mode) 683 bool copybitDone = false; 684 if(ctx->mCopyBit[dpy]) 685 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); 686 687 if(list->numHwLayers > 1) 688 hwc_sync(ctx, list, dpy, fd); 689 690 // Dump the layers for external 691 if(ctx->mHwcDebug[dpy]) 692 ctx->mHwcDebug[dpy]->dumpLayers(list); 693 694 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { 695 ALOGE("%s: MDPComp draw failed", __FUNCTION__); 696 ret = -1; 697 } 698 699 int extOnlyLayerIndex = 700 ctx->listStats[dpy].extOnlyLayerIndex; 701 702 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 703 if(extOnlyLayerIndex!= -1) { 704 hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex]; 705 hnd = (private_handle_t *)extLayer->handle; 706 } else if(copybitDone) { 707 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer(); 708 } 709 710 if(hnd && !isYuvBuffer(hnd)) { 711 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { 712 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 713 ret = -1; 714 } 715 } 716 717 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 718 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); 719 ret = -1; 720 } 721 } 722 723 closeAcquireFds(list); 724 return ret; 725} 726 727static int hwc_set(hwc_composer_device_1 *dev, 728 size_t numDisplays, 729 hwc_display_contents_1_t** displays) 730{ 731 int ret = 0; 732 hwc_context_t* ctx = (hwc_context_t*)(dev); 733 for (int i = 0; i < (int)numDisplays; i++) { 734 hwc_display_contents_1_t* list = displays[i]; 735 int dpy = getDpyforExternalDisplay(ctx, i); 736 switch(dpy) { 737 case HWC_DISPLAY_PRIMARY: 738 ret = hwc_set_primary(ctx, list); 739 break; 740 case HWC_DISPLAY_EXTERNAL: 741 ret = hwc_set_external(ctx, list); 742 break; 743 case HWC_DISPLAY_VIRTUAL: 744 if(ctx->mHWCVirtual) 745 ret = ctx->mHWCVirtual->set(ctx, list); 746 break; 747 default: 748 ret = -EINVAL; 749 } 750 } 751 // This is only indicative of how many times SurfaceFlinger posts 752 // frames to the display. 753 CALC_FPS(); 754 MDPComp::resetIdleFallBack(); 755 ctx->mVideoTransFlag = false; 756 //Was locked at the beginning of prepare 757 ctx->mDrawLock.unlock(); 758 return ret; 759} 760 761int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp, 762 uint32_t* configs, size_t* numConfigs) { 763 int ret = 0; 764 hwc_context_t* ctx = (hwc_context_t*)(dev); 765 disp = getDpyforExternalDisplay(ctx, disp); 766 //in 1.1 there is no way to choose a config, report as config id # 0 767 //This config is passed to getDisplayAttributes. Ignore for now. 768 switch(disp) { 769 case HWC_DISPLAY_PRIMARY: 770 if(*numConfigs > 0) { 771 configs[0] = 0; 772 *numConfigs = 1; 773 } 774 ret = 0; //NO_ERROR 775 break; 776 case HWC_DISPLAY_EXTERNAL: 777 case HWC_DISPLAY_VIRTUAL: 778 ret = -1; //Not connected 779 if(ctx->dpyAttr[disp].connected) { 780 ret = 0; //NO_ERROR 781 if(*numConfigs > 0) { 782 configs[0] = 0; 783 *numConfigs = 1; 784 } 785 } 786 break; 787 } 788 return ret; 789} 790 791int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp, 792 uint32_t /*config*/, const uint32_t* attributes, int32_t* values) { 793 794 hwc_context_t* ctx = (hwc_context_t*)(dev); 795 disp = getDpyforExternalDisplay(ctx, disp); 796 //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error 797 if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) { 798 return -1; 799 } 800 801 //From HWComposer 802 static const uint32_t DISPLAY_ATTRIBUTES[] = { 803 HWC_DISPLAY_VSYNC_PERIOD, 804 HWC_DISPLAY_WIDTH, 805 HWC_DISPLAY_HEIGHT, 806 HWC_DISPLAY_DPI_X, 807 HWC_DISPLAY_DPI_Y, 808 HWC_DISPLAY_NO_ATTRIBUTE, 809 }; 810 811 const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) / 812 sizeof(DISPLAY_ATTRIBUTES)[0]); 813 814 for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) { 815 switch (attributes[i]) { 816 case HWC_DISPLAY_VSYNC_PERIOD: 817 values[i] = ctx->dpyAttr[disp].vsync_period; 818 break; 819 case HWC_DISPLAY_WIDTH: 820 values[i] = ctx->dpyAttr[disp].xres; 821 ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp, 822 ctx->dpyAttr[disp].xres); 823 break; 824 case HWC_DISPLAY_HEIGHT: 825 values[i] = ctx->dpyAttr[disp].yres; 826 ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp, 827 ctx->dpyAttr[disp].yres); 828 break; 829 case HWC_DISPLAY_DPI_X: 830 values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0); 831 break; 832 case HWC_DISPLAY_DPI_Y: 833 values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0); 834 break; 835 default: 836 ALOGE("Unknown display attribute %d", 837 attributes[i]); 838 return -EINVAL; 839 } 840 } 841 return 0; 842} 843 844void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len) 845{ 846 hwc_context_t* ctx = (hwc_context_t*)(dev); 847 Locker::Autolock _l(ctx->mDrawLock); 848 android::String8 aBuf(""); 849 dumpsys_log(aBuf, "Qualcomm HWC state:\n"); 850 dumpsys_log(aBuf, " MDPVersion=%d\n", ctx->mMDP.version); 851 dumpsys_log(aBuf, " DisplayPanel=%c\n", ctx->mMDP.panel); 852 if(ctx->vstate.fakevsync) 853 dumpsys_log(aBuf, " Vsync is being faked!!\n"); 854 for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) { 855 if(ctx->mMDPComp[dpy]) 856 ctx->mMDPComp[dpy]->dump(aBuf); 857 } 858 char ovDump[2048] = {'\0'}; 859 ctx->mOverlay->getDump(ovDump, 2048); 860 dumpsys_log(aBuf, ovDump); 861 ovDump[0] = '\0'; 862 ctx->mRotMgr->getDump(ovDump, 1024); 863 dumpsys_log(aBuf, ovDump); 864 ovDump[0] = '\0'; 865 if(Writeback::getDump(ovDump, 1024)) { 866 dumpsys_log(aBuf, ovDump); 867 ovDump[0] = '\0'; 868 } 869 strlcpy(buff, aBuf.string(), buff_len); 870} 871 872static int hwc_device_close(struct hw_device_t *dev) 873{ 874 if(!dev) { 875 ALOGE("%s: NULL device pointer", __FUNCTION__); 876 return -1; 877 } 878 closeContext((hwc_context_t*)dev); 879 free(dev); 880 881 return 0; 882} 883 884static int hwc_device_open(const struct hw_module_t* module, const char* name, 885 struct hw_device_t** device) 886{ 887 int status = -EINVAL; 888 889 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 890 struct hwc_context_t *dev; 891 dev = (hwc_context_t*)malloc(sizeof(*dev)); 892 if(dev == NULL) 893 return status; 894 memset(dev, 0, sizeof(*dev)); 895 896 //Initialize hwc context 897 initContext(dev); 898 899 //Setup HWC methods 900 dev->device.common.tag = HARDWARE_DEVICE_TAG; 901 dev->device.common.version = HWC_DEVICE_API_VERSION_1_3; 902 dev->device.common.module = const_cast<hw_module_t*>(module); 903 dev->device.common.close = hwc_device_close; 904 dev->device.prepare = hwc_prepare; 905 dev->device.set = hwc_set; 906 dev->device.eventControl = hwc_eventControl; 907 dev->device.blank = hwc_blank; 908 dev->device.query = hwc_query; 909 dev->device.registerProcs = hwc_registerProcs; 910 dev->device.dump = hwc_dump; 911 dev->device.getDisplayConfigs = hwc_getDisplayConfigs; 912 dev->device.getDisplayAttributes = hwc_getDisplayAttributes; 913 *device = &dev->device.common; 914 status = 0; 915 } 916 return status; 917} 918