hwc.cpp revision 53b0b5fcf40f174642b0a58cba91b5479d31fe91
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 ctx->mOverlay->isDMAMultiplexingSupported()) { 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 229static void scaleDisplayFrame(hwc_context_t *ctx, int dpy, 230 hwc_display_contents_1_t *list) { 231 uint32_t origXres = ctx->dpyAttr[dpy].xres; 232 uint32_t origYres = ctx->dpyAttr[dpy].yres; 233 uint32_t newXres = ctx->dpyAttr[dpy].xres_new; 234 uint32_t newYres = ctx->dpyAttr[dpy].yres_new; 235 float xresRatio = (float)origXres / (float)newXres; 236 float yresRatio = (float)origYres / (float)newYres; 237 for (size_t i = 0; i < list->numHwLayers; i++) { 238 hwc_layer_1_t *layer = &list->hwLayers[i]; 239 hwc_rect_t& displayFrame = layer->displayFrame; 240 hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf); 241 uint32_t layerWidth = displayFrame.right - displayFrame.left; 242 uint32_t layerHeight = displayFrame.bottom - displayFrame.top; 243 displayFrame.left = (int)(xresRatio * (float)displayFrame.left); 244 displayFrame.top = (int)(yresRatio * (float)displayFrame.top); 245 displayFrame.right = (int)((float)displayFrame.left + 246 (float)layerWidth * xresRatio); 247 displayFrame.bottom = (int)((float)displayFrame.top + 248 (float)layerHeight * yresRatio); 249 } 250} 251 252static int hwc_prepare_primary(hwc_composer_device_1 *dev, 253 hwc_display_contents_1_t *list) { 254 ATRACE_CALL(); 255 hwc_context_t* ctx = (hwc_context_t*)(dev); 256 const int dpy = HWC_DISPLAY_PRIMARY; 257 bool fbComp = false; 258 if (LIKELY(list && list->numHwLayers > 1) && 259 ctx->dpyAttr[dpy].isActive) { 260 261 if (ctx->dpyAttr[dpy].customFBSize && 262 list->flags & HWC_GEOMETRY_CHANGED) 263 scaleDisplayFrame(ctx, dpy, list); 264 265 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1); 266 setListStats(ctx, list, dpy); 267 268 fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0); 269 270 if (fbComp) { 271 const int fbZ = 0; 272 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) { 273 ctx->mOverlay->clear(dpy); 274 ctx->mLayerRotMap[dpy]->clear(); 275 } 276 } 277 278 if (ctx->mMDP.version < qdutils::MDP_V4_0) { 279 if(ctx->mCopyBit[dpy]) 280 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy); 281 } 282 setGPUHint(ctx, list); 283 } 284 return 0; 285} 286 287static int hwc_prepare_external(hwc_composer_device_1 *dev, 288 hwc_display_contents_1_t *list) { 289 ATRACE_CALL(); 290 hwc_context_t* ctx = (hwc_context_t*)(dev); 291 const int dpy = HWC_DISPLAY_EXTERNAL; 292 293 if (LIKELY(list && list->numHwLayers > 1) && 294 ctx->dpyAttr[dpy].isActive && 295 ctx->dpyAttr[dpy].connected) { 296 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1); 297 if(!ctx->dpyAttr[dpy].isPause) { 298 ctx->dpyAttr[dpy].isConfiguring = false; 299 setListStats(ctx, list, dpy); 300 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) { 301 const int fbZ = 0; 302 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) 303 { 304 ctx->mOverlay->clear(dpy); 305 ctx->mLayerRotMap[dpy]->clear(); 306 } 307 } 308 } else { 309 /* External Display is in Pause state. 310 * Mark all application layers as OVERLAY so that 311 * GPU will not compose. 312 */ 313 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) { 314 hwc_layer_1_t *layer = &list->hwLayers[i]; 315 layer->compositionType = HWC_OVERLAY; 316 } 317 } 318 } 319 return 0; 320} 321 322static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, 323 hwc_display_contents_1_t** displays) 324{ 325 int ret = 0; 326 hwc_context_t* ctx = (hwc_context_t*)(dev); 327 328 if (ctx->mPanelResetStatus) { 329 ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__); 330 reset_panel(dev); 331 } 332 333 //Will be unlocked at the end of set 334 ctx->mDrawLock.lock(); 335 setPaddingRound(ctx,numDisplays,displays); 336 setDMAState(ctx,numDisplays,displays); 337 setNumActiveDisplays(ctx,numDisplays,displays); 338 reset(ctx, (int)numDisplays, displays); 339 340 ctx->mOverlay->configBegin(); 341 ctx->mRotMgr->configBegin(); 342 overlay::Writeback::configBegin(); 343 344 for (int32_t i = ((int32_t)numDisplays-1); i >=0 ; i--) { 345 hwc_display_contents_1_t *list = displays[i]; 346 int dpy = getDpyforExternalDisplay(ctx, i); 347 switch(dpy) { 348 case HWC_DISPLAY_PRIMARY: 349 ret = hwc_prepare_primary(dev, list); 350 break; 351 case HWC_DISPLAY_EXTERNAL: 352 ret = hwc_prepare_external(dev, list); 353 break; 354 case HWC_DISPLAY_VIRTUAL: 355 if(ctx->mHWCVirtual) 356 ret = ctx->mHWCVirtual->prepare(dev, list); 357 break; 358 default: 359 ret = -EINVAL; 360 } 361 } 362 363 ctx->mOverlay->configDone(); 364 ctx->mRotMgr->configDone(); 365 overlay::Writeback::configDone(); 366 367 return ret; 368} 369 370static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy, 371 int event, int enable) 372{ 373 ATRACE_CALL(); 374 int ret = 0; 375 hwc_context_t* ctx = (hwc_context_t*)(dev); 376 switch(event) { 377 case HWC_EVENT_VSYNC: 378 if (ctx->vstate.enable == enable) 379 break; 380 ret = hwc_vsync_control(ctx, dpy, enable); 381 if(ret == 0) 382 ctx->vstate.enable = !!enable; 383 ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s", 384 (enable)?"ENABLED":"DISABLED"); 385 break; 386#ifdef QCOM_BSP 387 case HWC_EVENT_ORIENTATION: 388 if(dpy == HWC_DISPLAY_PRIMARY) { 389 Locker::Autolock _l(ctx->mDrawLock); 390 // store the primary display orientation 391 ctx->deviceOrientation = enable; 392 } 393 break; 394#endif 395 default: 396 ret = -EINVAL; 397 } 398 return ret; 399} 400 401static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank) 402{ 403 ATRACE_CALL(); 404 hwc_context_t* ctx = (hwc_context_t*)(dev); 405 406 Locker::Autolock _l(ctx->mDrawLock); 407 int ret = 0, value = 0; 408 409 /* In case of non-hybrid WFD session, we are fooling SF by 410 * piggybacking on HDMI display ID for virtual. 411 * TODO: Not needed once we have WFD client working on top 412 * of Google API's. 413 */ 414 dpy = getDpyforExternalDisplay(ctx,dpy); 415 416 ALOGD_IF(BLANK_DEBUG, "%s: %s display: %d", __FUNCTION__, 417 blank==1 ? "Blanking":"Unblanking", dpy); 418 if(blank) { 419 // free up all the overlay pipes in use 420 // when we get a blank for either display 421 // makes sure that all pipes are freed 422 ctx->mOverlay->configBegin(); 423 ctx->mOverlay->configDone(); 424 ctx->mRotMgr->clear(); 425 // If VDS is connected, do not clear WB object as it 426 // will end up detaching IOMMU. This is required 427 // to send black frame to WFD sink on power suspend. 428 // Note: With this change, we keep the WriteBack object 429 // alive on power suspend for AD use case. 430 } 431 switch(dpy) { 432 case HWC_DISPLAY_PRIMARY: 433 value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK; 434 if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) { 435 ALOGE("%s: Failed to handle blank event(%d) for Primary!!", 436 __FUNCTION__, blank ); 437 return -1; 438 } 439 440 if(!blank) { 441 // Enable HPD here, as during bootup unblank is called 442 // when SF is completely initialized 443 ctx->mExtDisplay->setHPD(1); 444 } 445 446 ctx->dpyAttr[dpy].isActive = !blank; 447 448 if(ctx->mVirtualonExtActive) { 449 /* if mVirtualonExtActive is true, display hal will 450 * receive unblank calls for non-hybrid WFD solution 451 * since we piggyback on HDMI. 452 * TODO: Not needed once we have WFD client working on top 453 of Google API's */ 454 break; 455 } 456 case HWC_DISPLAY_VIRTUAL: 457 /* There are two ways to reach this block of code. 458 459 * Display hal has received unblank call on HWC_DISPLAY_EXTERNAL 460 and ctx->mVirtualonExtActive is true. In this case, non-hybrid 461 WFD is active. If so, getDpyforExternalDisplay will return dpy 462 as HWC_DISPLAY_VIRTUAL. 463 464 * Display hal has received unblank call on HWC_DISPLAY_PRIMARY 465 and since SF is not aware of VIRTUAL DISPLAY being handle by HWC, 466 it wont send blank / unblank events for it. We piggyback on 467 PRIMARY DISPLAY events to release mdp pipes and 468 activate/deactivate VIRTUAL DISPLAY. 469 470 * TODO: This separate case statement is not needed once we have 471 WFD client working on top of Google API's. 472 473 */ 474 475 if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) { 476 if(blank and (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause)) { 477 int dpy = HWC_DISPLAY_VIRTUAL; 478 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 479 ALOGE("%s: display commit fail for virtual!", __FUNCTION__); 480 ret = -1; 481 } 482 } 483 ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank; 484 } 485 break; 486 case HWC_DISPLAY_EXTERNAL: 487 if(blank) { 488 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 489 ALOGE("%s: display commit fail for external!", __FUNCTION__); 490 ret = -1; 491 } 492 } 493 ctx->dpyAttr[dpy].isActive = !blank; 494 break; 495 default: 496 return -EINVAL; 497 } 498 499 ALOGD_IF(BLANK_DEBUG, "%s: Done %s display: %d", __FUNCTION__, 500 blank ? "blanking":"unblanking", dpy); 501 return ret; 502} 503 504static void reset_panel(struct hwc_composer_device_1* dev) 505{ 506 int ret = 0; 507 hwc_context_t* ctx = (hwc_context_t*)(dev); 508 509 if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) { 510 ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__); 511 ctx->mPanelResetStatus = false; 512 return; 513 } 514 515 ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__); 516 ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1); 517 if (ret < 0) { 518 ALOGE("%s: FBIOBLANK failed to BLANK: %s", __FUNCTION__, 519 strerror(errno)); 520 } 521 522 ALOGD("%s: calling UNBLANK DISPLAY and enabling vsync", __FUNCTION__); 523 ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 0); 524 if (ret < 0) { 525 ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__, 526 strerror(errno)); 527 } 528 hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1); 529 530 ctx->mPanelResetStatus = false; 531} 532 533 534static int hwc_query(struct hwc_composer_device_1* dev, 535 int param, int* value) 536{ 537 hwc_context_t* ctx = (hwc_context_t*)(dev); 538 int supported = HWC_DISPLAY_PRIMARY_BIT; 539 540 switch (param) { 541 case HWC_BACKGROUND_LAYER_SUPPORTED: 542 // Not supported for now 543 value[0] = 0; 544 break; 545 case HWC_DISPLAY_TYPES_SUPPORTED: 546 if(ctx->mMDP.hasOverlay) { 547 supported |= HWC_DISPLAY_VIRTUAL_BIT; 548 if(!(qdutils::MDPVersion::getInstance().is8x26() || 549 qdutils::MDPVersion::getInstance().is8x16())) 550 supported |= HWC_DISPLAY_EXTERNAL_BIT; 551 } 552 value[0] = supported; 553 break; 554 case HWC_FORMAT_RB_SWAP: 555 value[0] = 1; 556 break; 557 case HWC_COLOR_FILL: 558 value[0] = 1; 559 break; 560 default: 561 return -EINVAL; 562 } 563 return 0; 564 565} 566 567 568static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 569 ATRACE_CALL(); 570 int ret = 0; 571 const int dpy = HWC_DISPLAY_PRIMARY; 572 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) { 573 size_t last = list->numHwLayers - 1; 574 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 575 int fd = -1; //FenceFD from the Copybit(valid in async mode) 576 bool copybitDone = false; 577 if(ctx->mCopyBit[dpy]) 578 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); 579 if(list->numHwLayers > 1) 580 hwc_sync(ctx, list, dpy, fd); 581 582 // Dump the layers for primary 583 if(ctx->mHwcDebug[dpy]) 584 ctx->mHwcDebug[dpy]->dumpLayers(list); 585 586 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { 587 ALOGE("%s: MDPComp draw failed", __FUNCTION__); 588 ret = -1; 589 } 590 591 //TODO We dont check for SKIP flag on this layer because we need PAN 592 //always. Last layer is always FB 593 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 594 if(copybitDone && ctx->mMDP.version >= qdutils::MDP_V4_0) { 595 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer(); 596 } 597 598 if(hnd) { 599 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { 600 ALOGE("%s: FBUpdate draw failed", __FUNCTION__); 601 ret = -1; 602 } 603 } 604 605 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, 606 ctx->listStats[dpy].roi)) { 607 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); 608 ret = -1; 609 } 610 611 } 612 613 closeAcquireFds(list); 614 return ret; 615} 616 617static int hwc_set_external(hwc_context_t *ctx, 618 hwc_display_contents_1_t* list) 619{ 620 ATRACE_CALL(); 621 int ret = 0; 622 623 const int dpy = HWC_DISPLAY_EXTERNAL; 624 625 626 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive && 627 ctx->dpyAttr[dpy].connected && 628 !ctx->dpyAttr[dpy].isPause) { 629 size_t last = list->numHwLayers - 1; 630 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 631 int fd = -1; //FenceFD from the Copybit(valid in async mode) 632 bool copybitDone = false; 633 if(ctx->mCopyBit[dpy]) 634 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); 635 636 if(list->numHwLayers > 1) 637 hwc_sync(ctx, list, dpy, fd); 638 639 // Dump the layers for external 640 if(ctx->mHwcDebug[dpy]) 641 ctx->mHwcDebug[dpy]->dumpLayers(list); 642 643 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { 644 ALOGE("%s: MDPComp draw failed", __FUNCTION__); 645 ret = -1; 646 } 647 648 int extOnlyLayerIndex = 649 ctx->listStats[dpy].extOnlyLayerIndex; 650 651 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 652 if(extOnlyLayerIndex!= -1) { 653 hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex]; 654 hnd = (private_handle_t *)extLayer->handle; 655 } else if(copybitDone) { 656 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer(); 657 } 658 659 if(hnd && !isYuvBuffer(hnd)) { 660 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { 661 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 662 ret = -1; 663 } 664 } 665 666 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 667 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); 668 ret = -1; 669 } 670 } 671 672 closeAcquireFds(list); 673 return ret; 674} 675 676static int hwc_set(hwc_composer_device_1 *dev, 677 size_t numDisplays, 678 hwc_display_contents_1_t** displays) 679{ 680 int ret = 0; 681 hwc_context_t* ctx = (hwc_context_t*)(dev); 682 for (int i = 0; i < (int)numDisplays; i++) { 683 hwc_display_contents_1_t* list = displays[i]; 684 int dpy = getDpyforExternalDisplay(ctx, i); 685 switch(dpy) { 686 case HWC_DISPLAY_PRIMARY: 687 ret = hwc_set_primary(ctx, list); 688 break; 689 case HWC_DISPLAY_EXTERNAL: 690 ret = hwc_set_external(ctx, list); 691 break; 692 case HWC_DISPLAY_VIRTUAL: 693 if(ctx->mHWCVirtual) 694 ret = ctx->mHWCVirtual->set(ctx, list); 695 break; 696 default: 697 ret = -EINVAL; 698 } 699 } 700 // This is only indicative of how many times SurfaceFlinger posts 701 // frames to the display. 702 CALC_FPS(); 703 MDPComp::resetIdleFallBack(); 704 ctx->mVideoTransFlag = false; 705 //Was locked at the beginning of prepare 706 ctx->mDrawLock.unlock(); 707 return ret; 708} 709 710int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp, 711 uint32_t* configs, size_t* numConfigs) { 712 int ret = 0; 713 hwc_context_t* ctx = (hwc_context_t*)(dev); 714 disp = getDpyforExternalDisplay(ctx, disp); 715 //in 1.1 there is no way to choose a config, report as config id # 0 716 //This config is passed to getDisplayAttributes. Ignore for now. 717 switch(disp) { 718 case HWC_DISPLAY_PRIMARY: 719 if(*numConfigs > 0) { 720 configs[0] = 0; 721 *numConfigs = 1; 722 } 723 ret = 0; //NO_ERROR 724 break; 725 case HWC_DISPLAY_EXTERNAL: 726 case HWC_DISPLAY_VIRTUAL: 727 ret = -1; //Not connected 728 if(ctx->dpyAttr[disp].connected) { 729 ret = 0; //NO_ERROR 730 if(*numConfigs > 0) { 731 configs[0] = 0; 732 *numConfigs = 1; 733 } 734 } 735 break; 736 } 737 return ret; 738} 739 740int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp, 741 uint32_t /*config*/, const uint32_t* attributes, int32_t* values) { 742 743 hwc_context_t* ctx = (hwc_context_t*)(dev); 744 disp = getDpyforExternalDisplay(ctx, disp); 745 //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error 746 if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) { 747 return -1; 748 } 749 750 //From HWComposer 751 static const uint32_t DISPLAY_ATTRIBUTES[] = { 752 HWC_DISPLAY_VSYNC_PERIOD, 753 HWC_DISPLAY_WIDTH, 754 HWC_DISPLAY_HEIGHT, 755 HWC_DISPLAY_DPI_X, 756 HWC_DISPLAY_DPI_Y, 757 HWC_DISPLAY_NO_ATTRIBUTE, 758 }; 759 760 const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) / 761 sizeof(DISPLAY_ATTRIBUTES)[0]); 762 763 for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) { 764 switch (attributes[i]) { 765 case HWC_DISPLAY_VSYNC_PERIOD: 766 values[i] = ctx->dpyAttr[disp].vsync_period; 767 break; 768 case HWC_DISPLAY_WIDTH: 769 if (ctx->dpyAttr[disp].customFBSize) 770 values[i] = ctx->dpyAttr[disp].xres_new; 771 else 772 values[i] = ctx->dpyAttr[disp].xres; 773 774 ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp, 775 values[i]); 776 break; 777 case HWC_DISPLAY_HEIGHT: 778 if (ctx->dpyAttr[disp].customFBSize) 779 values[i] = ctx->dpyAttr[disp].yres_new; 780 else 781 values[i] = ctx->dpyAttr[disp].yres; 782 ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp, 783 values[i]); 784 break; 785 case HWC_DISPLAY_DPI_X: 786 values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0); 787 break; 788 case HWC_DISPLAY_DPI_Y: 789 values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0); 790 break; 791 default: 792 ALOGE("Unknown display attribute %d", 793 attributes[i]); 794 return -EINVAL; 795 } 796 } 797 return 0; 798} 799 800void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len) 801{ 802 hwc_context_t* ctx = (hwc_context_t*)(dev); 803 Locker::Autolock _l(ctx->mDrawLock); 804 android::String8 aBuf(""); 805 dumpsys_log(aBuf, "Qualcomm HWC state:\n"); 806 dumpsys_log(aBuf, " MDPVersion=%d\n", ctx->mMDP.version); 807 dumpsys_log(aBuf, " DisplayPanel=%c\n", ctx->mMDP.panel); 808 if(ctx->vstate.fakevsync) 809 dumpsys_log(aBuf, " Vsync is being faked!!\n"); 810 for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) { 811 if(ctx->mMDPComp[dpy]) 812 ctx->mMDPComp[dpy]->dump(aBuf); 813 } 814 char ovDump[2048] = {'\0'}; 815 ctx->mOverlay->getDump(ovDump, 2048); 816 dumpsys_log(aBuf, ovDump); 817 ovDump[0] = '\0'; 818 ctx->mRotMgr->getDump(ovDump, 1024); 819 dumpsys_log(aBuf, ovDump); 820 ovDump[0] = '\0'; 821 if(Writeback::getDump(ovDump, 1024)) { 822 dumpsys_log(aBuf, ovDump); 823 ovDump[0] = '\0'; 824 } 825 strlcpy(buff, aBuf.string(), buff_len); 826} 827 828static int hwc_device_close(struct hw_device_t *dev) 829{ 830 if(!dev) { 831 ALOGE("%s: NULL device pointer", __FUNCTION__); 832 return -1; 833 } 834 closeContext((hwc_context_t*)dev); 835 free(dev); 836 837 return 0; 838} 839 840static int hwc_device_open(const struct hw_module_t* module, const char* name, 841 struct hw_device_t** device) 842{ 843 int status = -EINVAL; 844 845 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 846 struct hwc_context_t *dev; 847 dev = (hwc_context_t*)malloc(sizeof(*dev)); 848 if(dev == NULL) 849 return status; 850 memset(dev, 0, sizeof(*dev)); 851 852 //Initialize hwc context 853 initContext(dev); 854 855 //Setup HWC methods 856 dev->device.common.tag = HARDWARE_DEVICE_TAG; 857 dev->device.common.version = HWC_DEVICE_API_VERSION_1_3; 858 dev->device.common.module = const_cast<hw_module_t*>(module); 859 dev->device.common.close = hwc_device_close; 860 dev->device.prepare = hwc_prepare; 861 dev->device.set = hwc_set; 862 dev->device.eventControl = hwc_eventControl; 863 dev->device.blank = hwc_blank; 864 dev->device.query = hwc_query; 865 dev->device.registerProcs = hwc_registerProcs; 866 dev->device.dump = hwc_dump; 867 dev->device.getDisplayConfigs = hwc_getDisplayConfigs; 868 dev->device.getDisplayAttributes = hwc_getDisplayAttributes; 869 *device = &dev->device.common; 870 status = 0; 871 } 872 return status; 873} 874