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