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