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