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