hwc.cpp revision bd51df0d51c9342f705caeea9c245b919dedb120
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved. 4 * 5 * Not a Contribution, Apache license notifications and license are retained 6 * for attribution purposes only. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL) 21#include <fcntl.h> 22#include <errno.h> 23 24#include <cutils/log.h> 25#include <cutils/atomic.h> 26#include <EGL/egl.h> 27#include <utils/Trace.h> 28#include <sys/ioctl.h> 29#include <overlay.h> 30#include <overlayRotator.h> 31#include <overlayWriteback.h> 32#include <mdp_version.h> 33#include "hwc_utils.h" 34#include "hwc_fbupdate.h" 35#include "hwc_mdpcomp.h" 36#include "hwc_dump_layers.h" 37#include "external.h" 38#include "hwc_copybit.h" 39#include "hwc_ad.h" 40#include "profiler.h" 41#include "hwc_virtual.h" 42 43using namespace qhwc; 44using namespace overlay; 45 46#define VSYNC_DEBUG 0 47#define BLANK_DEBUG 1 48 49static int hwc_device_open(const struct hw_module_t* module, 50 const char* name, 51 struct hw_device_t** device); 52 53static struct hw_module_methods_t hwc_module_methods = { 54 open: hwc_device_open 55}; 56 57static void reset_panel(struct hwc_composer_device_1* dev); 58 59hwc_module_t HAL_MODULE_INFO_SYM = { 60 common: { 61 tag: HARDWARE_MODULE_TAG, 62 version_major: 2, 63 version_minor: 0, 64 id: HWC_HARDWARE_MODULE_ID, 65 name: "Qualcomm Hardware Composer Module", 66 author: "CodeAurora Forum", 67 methods: &hwc_module_methods, 68 dso: 0, 69 reserved: {0}, 70 } 71}; 72 73/* In case of non-hybrid WFD session, we are fooling SF by piggybacking on 74 * HDMI display ID for virtual. This helper is needed to differentiate their 75 * paths in HAL. 76 * TODO: Not needed once we have WFD client working on top of Google API's */ 77 78static int getDpyforExternalDisplay(hwc_context_t *ctx, int dpy) { 79 if(dpy == HWC_DISPLAY_EXTERNAL && ctx->mVirtualonExtActive) 80 return HWC_DISPLAY_VIRTUAL; 81 return dpy; 82} 83 84/* 85 * Save callback functions registered to HWC 86 */ 87static void hwc_registerProcs(struct hwc_composer_device_1* dev, 88 hwc_procs_t const* procs) 89{ 90 ALOGI("%s", __FUNCTION__); 91 hwc_context_t* ctx = (hwc_context_t*)(dev); 92 if(!ctx) { 93 ALOGE("%s: Invalid context", __FUNCTION__); 94 return; 95 } 96 ctx->proc = procs; 97 98 // Now that we have the functions needed, kick off 99 // the uevent & vsync threads 100 init_uevent_thread(ctx); 101 init_vsync_thread(ctx); 102} 103 104static void setPaddingRound(hwc_context_t *ctx, int numDisplays, 105 hwc_display_contents_1_t** displays) { 106 ctx->isPaddingRound = false; 107 for(int i = 0; i < numDisplays; i++) { 108 hwc_display_contents_1_t *list = displays[i]; 109 if (LIKELY(list && list->numHwLayers > 0)) { 110 if((ctx->mPrevHwLayerCount[i] == 1 or 111 ctx->mPrevHwLayerCount[i] == 0) and 112 (list->numHwLayers > 1)) { 113 /* If the previous cycle for dpy 'i' has 0 AppLayers and the 114 * current cycle has atleast 1 AppLayer, padding round needs 115 * to be invoked in current cycle on all the active displays 116 * to free up the resources. 117 */ 118 ctx->isPaddingRound = true; 119 } 120 ctx->mPrevHwLayerCount[i] = (int)list->numHwLayers; 121 } else { 122 ctx->mPrevHwLayerCount[i] = 0; 123 } 124 } 125} 126 127/* Based on certain conditions, isPaddingRound will be set 128 * to make this function self-contained */ 129static void setDMAState(hwc_context_t *ctx, int numDisplays, 130 hwc_display_contents_1_t** displays) { 131 132 if(ctx->mRotMgr->getNumActiveSessions() == 0) 133 Overlay::setDMAMode(Overlay::DMA_LINE_MODE); 134 135 for(int dpy = 0; dpy < numDisplays; dpy++) { 136 hwc_display_contents_1_t *list = displays[dpy]; 137 if (LIKELY(list && list->numHwLayers > 0)) { 138 for(size_t layerIndex = 0; layerIndex < list->numHwLayers; 139 layerIndex++) { 140 if(list->hwLayers[layerIndex].compositionType != 141 HWC_FRAMEBUFFER_TARGET) 142 { 143 hwc_layer_1_t const* layer = &list->hwLayers[layerIndex]; 144 private_handle_t *hnd = (private_handle_t *)layer->handle; 145 146 /* If a video layer requires rotation, set the DMA state 147 * to BLOCK_MODE */ 148 149 if (UNLIKELY(isYuvBuffer(hnd)) && canUseRotator(ctx, dpy) && 150 (layer->transform & HWC_TRANSFORM_ROT_90)) { 151 if(not ctx->mOverlay->isDMAMultiplexingSupported()) { 152 if(ctx->mOverlay->isPipeTypeAttached( 153 overlay::utils::OV_MDP_PIPE_DMA)) 154 ctx->isPaddingRound = true; 155 } 156 Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE); 157 } 158 } 159 } 160 if(dpy) { 161 /* Uncomment the below code for testing purpose. 162 Assuming the orientation value is in terms of HAL_TRANSFORM, 163 this needs mapping to HAL, if its in different convention */ 164 165 /* char value[PROPERTY_VALUE_MAX]; 166 property_get("sys.ext_orientation", value, "0"); 167 ctx->mExtOrientation = atoi(value);*/ 168 169 if(ctx->mExtOrientation || ctx->mBufferMirrorMode) { 170 if(ctx->mOverlay->isPipeTypeAttached( 171 overlay::utils::OV_MDP_PIPE_DMA)) { 172 ctx->isPaddingRound = true; 173 } 174 Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE); 175 } 176 } 177 } 178 } 179} 180 181static void setNumActiveDisplays(hwc_context_t *ctx, int numDisplays, 182 hwc_display_contents_1_t** displays) { 183 184 ctx->numActiveDisplays = 0; 185 for(int i = 0; i < numDisplays; i++) { 186 hwc_display_contents_1_t *list = displays[i]; 187 if (LIKELY(list && list->numHwLayers > 0)) { 188 /* For display devices like SSD and screenrecord, we cannot 189 * rely on isActive and connected attributes of dpyAttr to 190 * determine if the displaydevice is active. Hence in case if 191 * the layer-list is non-null and numHwLayers > 0, we assume 192 * the display device to be active. 193 */ 194 ctx->numActiveDisplays += 1; 195 } 196 } 197} 198 199static void reset(hwc_context_t *ctx, int numDisplays, 200 hwc_display_contents_1_t** displays) { 201 202 203 for(int i = 0; i < numDisplays; i++) { 204 hwc_display_contents_1_t *list = displays[i]; 205 // XXX:SurfaceFlinger no longer guarantees that this 206 // value is reset on every prepare. However, for the layer 207 // cache we need to reset it. 208 // We can probably rethink that later on 209 if (LIKELY(list && list->numHwLayers > 0)) { 210 for(size_t j = 0; j < list->numHwLayers; j++) { 211 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET) 212 list->hwLayers[j].compositionType = HWC_FRAMEBUFFER; 213 } 214 215 } 216 217 if(ctx->mFBUpdate[i]) 218 ctx->mFBUpdate[i]->reset(); 219 if(ctx->mCopyBit[i]) 220 ctx->mCopyBit[i]->reset(); 221 if(ctx->mLayerRotMap[i]) 222 ctx->mLayerRotMap[i]->reset(); 223 } 224 225 ctx->mAD->reset(); 226 MDPComp::reset(); 227 if(ctx->mHWCVirtual) 228 ctx->mHWCVirtual->destroy(ctx, numDisplays, displays); 229} 230 231static void scaleDisplayFrame(hwc_context_t *ctx, int dpy, 232 hwc_display_contents_1_t *list) { 233 uint32_t origXres = ctx->dpyAttr[dpy].xres; 234 uint32_t origYres = ctx->dpyAttr[dpy].yres; 235 uint32_t newXres = ctx->dpyAttr[dpy].xres_new; 236 uint32_t newYres = ctx->dpyAttr[dpy].yres_new; 237 float xresRatio = (float)origXres / (float)newXres; 238 float yresRatio = (float)origYres / (float)newYres; 239 for (size_t i = 0; i < list->numHwLayers; i++) { 240 hwc_layer_1_t *layer = &list->hwLayers[i]; 241 hwc_rect_t& displayFrame = layer->displayFrame; 242 hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf); 243 uint32_t layerWidth = displayFrame.right - displayFrame.left; 244 uint32_t layerHeight = displayFrame.bottom - displayFrame.top; 245 displayFrame.left = (int)(xresRatio * (float)displayFrame.left); 246 displayFrame.top = (int)(yresRatio * (float)displayFrame.top); 247 displayFrame.right = (int)((float)displayFrame.left + 248 (float)layerWidth * xresRatio); 249 displayFrame.bottom = (int)((float)displayFrame.top + 250 (float)layerHeight * yresRatio); 251 } 252} 253 254static int hwc_prepare_primary(hwc_composer_device_1 *dev, 255 hwc_display_contents_1_t *list) { 256 ATRACE_CALL(); 257 hwc_context_t* ctx = (hwc_context_t*)(dev); 258 const int dpy = HWC_DISPLAY_PRIMARY; 259 bool fbComp = false; 260 if (LIKELY(list && list->numHwLayers > 1) && 261 ctx->dpyAttr[dpy].isActive) { 262 263 if (ctx->dpyAttr[dpy].customFBSize && 264 list->flags & HWC_GEOMETRY_CHANGED) 265 scaleDisplayFrame(ctx, dpy, list); 266 267 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1); 268 setListStats(ctx, list, dpy); 269 270 fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0); 271 272 if (fbComp) { 273 const int fbZ = 0; 274 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) { 275 ctx->mOverlay->clear(dpy); 276 ctx->mLayerRotMap[dpy]->clear(); 277 } 278 } 279 280 if (ctx->mMDP.version < qdutils::MDP_V4_0) { 281 if(ctx->mCopyBit[dpy]) 282 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy); 283 } 284 setGPUHint(ctx, list); 285 } 286 return 0; 287} 288 289static int hwc_prepare_external(hwc_composer_device_1 *dev, 290 hwc_display_contents_1_t *list) { 291 ATRACE_CALL(); 292 hwc_context_t* ctx = (hwc_context_t*)(dev); 293 const int dpy = HWC_DISPLAY_EXTERNAL; 294 295 if (LIKELY(list && list->numHwLayers > 1) && 296 ctx->dpyAttr[dpy].isActive && 297 ctx->dpyAttr[dpy].connected) { 298 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1); 299 if(!ctx->dpyAttr[dpy].isPause) { 300 ctx->dpyAttr[dpy].isConfiguring = false; 301 setListStats(ctx, list, dpy); 302 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) { 303 const int fbZ = 0; 304 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) 305 { 306 ctx->mOverlay->clear(dpy); 307 ctx->mLayerRotMap[dpy]->clear(); 308 } 309 } 310 } else { 311 /* External Display is in Pause state. 312 * Mark all application layers as OVERLAY so that 313 * GPU will not compose. 314 */ 315 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) { 316 hwc_layer_1_t *layer = &list->hwLayers[i]; 317 layer->compositionType = HWC_OVERLAY; 318 } 319 } 320 } 321 return 0; 322} 323 324static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, 325 hwc_display_contents_1_t** displays) 326{ 327 int ret = 0; 328 hwc_context_t* ctx = (hwc_context_t*)(dev); 329 330 if (ctx->mPanelResetStatus) { 331 ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__); 332 reset_panel(dev); 333 } 334 335 //Will be unlocked at the end of set 336 ctx->mDrawLock.lock(); 337 setPaddingRound(ctx,numDisplays,displays); 338 setDMAState(ctx,numDisplays,displays); 339 setNumActiveDisplays(ctx,numDisplays,displays); 340 reset(ctx, (int)numDisplays, displays); 341 342 ctx->mOverlay->configBegin(); 343 ctx->mRotMgr->configBegin(); 344 overlay::Writeback::configBegin(); 345 346 for (int32_t i = ((int32_t)numDisplays-1); i >=0 ; i--) { 347 hwc_display_contents_1_t *list = displays[i]; 348 int dpy = getDpyforExternalDisplay(ctx, i); 349 switch(dpy) { 350 case HWC_DISPLAY_PRIMARY: 351 ret = hwc_prepare_primary(dev, list); 352 break; 353 case HWC_DISPLAY_EXTERNAL: 354 ret = hwc_prepare_external(dev, list); 355 break; 356 case HWC_DISPLAY_VIRTUAL: 357 if(ctx->mHWCVirtual) 358 ret = ctx->mHWCVirtual->prepare(dev, list); 359 break; 360 default: 361 ret = -EINVAL; 362 } 363 } 364 365 ctx->mOverlay->configDone(); 366 ctx->mRotMgr->configDone(); 367 overlay::Writeback::configDone(); 368 369 return ret; 370} 371 372static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy, 373 int event, int enable) 374{ 375 ATRACE_CALL(); 376 int ret = 0; 377 hwc_context_t* ctx = (hwc_context_t*)(dev); 378 switch(event) { 379 case HWC_EVENT_VSYNC: 380 if (ctx->vstate.enable == enable) 381 break; 382 ret = hwc_vsync_control(ctx, dpy, enable); 383 if(ret == 0) 384 ctx->vstate.enable = !!enable; 385 ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s", 386 (enable)?"ENABLED":"DISABLED"); 387 break; 388#ifdef QCOM_BSP 389 case HWC_EVENT_ORIENTATION: 390 if(dpy == HWC_DISPLAY_PRIMARY) { 391 Locker::Autolock _l(ctx->mDrawLock); 392 // store the primary display orientation 393 ctx->deviceOrientation = enable; 394 } 395 break; 396#endif 397 default: 398 ret = -EINVAL; 399 } 400 return ret; 401} 402 403static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank) 404{ 405 ATRACE_CALL(); 406 hwc_context_t* ctx = (hwc_context_t*)(dev); 407 408 Locker::Autolock _l(ctx->mDrawLock); 409 int ret = 0, value = 0; 410 411 /* In case of non-hybrid WFD session, we are fooling SF by 412 * piggybacking on HDMI display ID for virtual. 413 * TODO: Not needed once we have WFD client working on top 414 * of Google API's. 415 */ 416 dpy = getDpyforExternalDisplay(ctx,dpy); 417 418 ALOGD_IF(BLANK_DEBUG, "%s: %s display: %d", __FUNCTION__, 419 blank==1 ? "Blanking":"Unblanking", dpy); 420 if(blank) { 421 // free up all the overlay pipes in use 422 // when we get a blank for either display 423 // makes sure that all pipes are freed 424 ctx->mOverlay->configBegin(); 425 ctx->mOverlay->configDone(); 426 ctx->mRotMgr->clear(); 427 overlay::Writeback::clear(); 428 } 429 switch(dpy) { 430 case HWC_DISPLAY_PRIMARY: 431 value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK; 432 if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) { 433 ALOGE("%s: Failed to handle blank event(%d) for Primary!!", 434 __FUNCTION__, blank ); 435 return -1; 436 } 437 438 if(!blank) { 439 // Enable HPD here, as during bootup unblank is called 440 // when SF is completely initialized 441 ctx->mExtDisplay->setHPD(1); 442 } 443 444 ctx->dpyAttr[dpy].isActive = !blank; 445 446 if(ctx->mVirtualonExtActive) { 447 /* if mVirtualonExtActive is true, display hal will 448 * receive unblank calls for non-hybrid WFD solution 449 * since we piggyback on HDMI. 450 * TODO: Not needed once we have WFD client working on top 451 of Google API's */ 452 break; 453 } 454 case HWC_DISPLAY_VIRTUAL: 455 /* There are two ways to reach this block of code. 456 457 * Display hal has received unblank call on HWC_DISPLAY_EXTERNAL 458 and ctx->mVirtualonExtActive is true. In this case, non-hybrid 459 WFD is active. If so, getDpyforExternalDisplay will return dpy 460 as HWC_DISPLAY_VIRTUAL. 461 462 * Display hal has received unblank call on HWC_DISPLAY_PRIMARY 463 and since SF is not aware of VIRTUAL DISPLAY being handle by HWC, 464 it wont send blank / unblank events for it. We piggyback on 465 PRIMARY DISPLAY events to release mdp pipes and 466 activate/deactivate VIRTUAL DISPLAY. 467 468 * TODO: This separate case statement is not needed once we have 469 WFD client working on top of Google API's. 470 471 */ 472 473 if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) { 474 if(blank and (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause)) { 475 int dpy = HWC_DISPLAY_VIRTUAL; 476 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 477 ALOGE("%s: display commit fail for virtual!", __FUNCTION__); 478 ret = -1; 479 } 480 } 481 value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK; 482 if(ioctl(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].fd, FBIOBLANK, value) < 0 483 ) { 484 ALOGE("%s: Failed to handle blank event(%d) for virtual!!", 485 __FUNCTION__, blank ); 486 return -1; 487 } 488 ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank; 489 } 490 break; 491 case HWC_DISPLAY_EXTERNAL: 492 if(blank) { 493 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 494 ALOGE("%s: display commit fail for external!", __FUNCTION__); 495 ret = -1; 496 } 497 } 498 ctx->dpyAttr[dpy].isActive = !blank; 499 break; 500 default: 501 return -EINVAL; 502 } 503 504 ALOGD_IF(BLANK_DEBUG, "%s: Done %s display: %d", __FUNCTION__, 505 blank ? "blanking":"unblanking", dpy); 506 return ret; 507} 508 509static void reset_panel(struct hwc_composer_device_1* dev) 510{ 511 int ret = 0; 512 hwc_context_t* ctx = (hwc_context_t*)(dev); 513 514 if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) { 515 ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__); 516 ctx->mPanelResetStatus = false; 517 return; 518 } 519 520 ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__); 521 ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1); 522 if (ret < 0) { 523 ALOGE("%s: FBIOBLANK failed to BLANK: %s", __FUNCTION__, 524 strerror(errno)); 525 } 526 527 ALOGD("%s: calling UNBLANK DISPLAY and enabling vsync", __FUNCTION__); 528 ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 0); 529 if (ret < 0) { 530 ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__, 531 strerror(errno)); 532 } 533 hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1); 534 535 ctx->mPanelResetStatus = false; 536} 537 538 539static int hwc_query(struct hwc_composer_device_1* dev, 540 int param, int* value) 541{ 542 hwc_context_t* ctx = (hwc_context_t*)(dev); 543 int supported = HWC_DISPLAY_PRIMARY_BIT; 544 545 switch (param) { 546 case HWC_BACKGROUND_LAYER_SUPPORTED: 547 // Not supported for now 548 value[0] = 0; 549 break; 550 case HWC_DISPLAY_TYPES_SUPPORTED: 551 if(ctx->mMDP.hasOverlay) { 552 supported |= HWC_DISPLAY_VIRTUAL_BIT; 553 if(!(qdutils::MDPVersion::getInstance().is8x26() || 554 qdutils::MDPVersion::getInstance().is8x16() || 555 qdutils::MDPVersion::getInstance().is8x39())) 556 supported |= HWC_DISPLAY_EXTERNAL_BIT; 557 } 558 value[0] = supported; 559 break; 560 case HWC_FORMAT_RB_SWAP: 561 value[0] = 1; 562 break; 563 case HWC_COLOR_FILL: 564 value[0] = 1; 565 break; 566 default: 567 return -EINVAL; 568 } 569 return 0; 570 571} 572 573 574static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 575 ATRACE_CALL(); 576 int ret = 0; 577 const int dpy = HWC_DISPLAY_PRIMARY; 578 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) { 579 size_t last = list->numHwLayers - 1; 580 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 581 int fd = -1; //FenceFD from the Copybit(valid in async mode) 582 bool copybitDone = false; 583 if(ctx->mCopyBit[dpy]) 584 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); 585 if(list->numHwLayers > 1) 586 hwc_sync(ctx, list, dpy, fd); 587 588 // Dump the layers for primary 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 //TODO We dont check for SKIP flag on this layer because we need PAN 598 //always. Last layer is always FB 599 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 600 if(copybitDone && ctx->mMDP.version >= qdutils::MDP_V4_0) { 601 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer(); 602 } 603 604 if(isAbcInUse(ctx) == true) { 605 int index = ctx->listStats[dpy].renderBufIndexforABC; 606 hwc_layer_1_t *tempLayer = &list->hwLayers[index]; 607 hnd = (private_handle_t *)tempLayer->handle; 608 } 609 610 if(hnd) { 611 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { 612 ALOGE("%s: FBUpdate draw failed", __FUNCTION__); 613 ret = -1; 614 } 615 } 616 617 int lSplit = getLeftSplit(ctx, dpy); 618 qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim( 619 ctx->listStats[dpy].lRoi.left, 620 ctx->listStats[dpy].lRoi.top, 621 ctx->listStats[dpy].lRoi.right - ctx->listStats[dpy].lRoi.left, 622 ctx->listStats[dpy].lRoi.bottom - ctx->listStats[dpy].lRoi.top); 623 624 qhwc::ovutils::Dim rRoi = qhwc::ovutils::Dim( 625 ctx->listStats[dpy].rRoi.left - lSplit, 626 ctx->listStats[dpy].rRoi.top, 627 ctx->listStats[dpy].rRoi.right - ctx->listStats[dpy].rRoi.left, 628 ctx->listStats[dpy].rRoi.bottom - ctx->listStats[dpy].rRoi.top); 629 630 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, lRoi, rRoi)) { 631 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); 632 ret = -1; 633 } 634 635 } 636 637 closeAcquireFds(list); 638 return ret; 639} 640 641static int hwc_set_external(hwc_context_t *ctx, 642 hwc_display_contents_1_t* list) 643{ 644 ATRACE_CALL(); 645 int ret = 0; 646 647 const int dpy = HWC_DISPLAY_EXTERNAL; 648 649 650 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive && 651 ctx->dpyAttr[dpy].connected && 652 !ctx->dpyAttr[dpy].isPause) { 653 size_t last = list->numHwLayers - 1; 654 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 655 int fd = -1; //FenceFD from the Copybit(valid in async mode) 656 bool copybitDone = false; 657 if(ctx->mCopyBit[dpy]) 658 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); 659 660 if(list->numHwLayers > 1) 661 hwc_sync(ctx, list, dpy, fd); 662 663 // Dump the layers for external 664 if(ctx->mHwcDebug[dpy]) 665 ctx->mHwcDebug[dpy]->dumpLayers(list); 666 667 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { 668 ALOGE("%s: MDPComp draw failed", __FUNCTION__); 669 ret = -1; 670 } 671 672 int extOnlyLayerIndex = 673 ctx->listStats[dpy].extOnlyLayerIndex; 674 675 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 676 if(extOnlyLayerIndex!= -1) { 677 hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex]; 678 hnd = (private_handle_t *)extLayer->handle; 679 } else if(copybitDone) { 680 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer(); 681 } 682 683 if(hnd && !isYuvBuffer(hnd)) { 684 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { 685 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 686 ret = -1; 687 } 688 } 689 690 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 691 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); 692 ret = -1; 693 } 694 } 695 696 closeAcquireFds(list); 697 return ret; 698} 699 700static int hwc_set(hwc_composer_device_1 *dev, 701 size_t numDisplays, 702 hwc_display_contents_1_t** displays) 703{ 704 int ret = 0; 705 hwc_context_t* ctx = (hwc_context_t*)(dev); 706 for (int i = 0; i < (int)numDisplays; i++) { 707 hwc_display_contents_1_t* list = displays[i]; 708 int dpy = getDpyforExternalDisplay(ctx, i); 709 switch(dpy) { 710 case HWC_DISPLAY_PRIMARY: 711 ret = hwc_set_primary(ctx, list); 712 break; 713 case HWC_DISPLAY_EXTERNAL: 714 ret = hwc_set_external(ctx, list); 715 break; 716 case HWC_DISPLAY_VIRTUAL: 717 if(ctx->mHWCVirtual) 718 ret = ctx->mHWCVirtual->set(ctx, list); 719 break; 720 default: 721 ret = -EINVAL; 722 } 723 } 724 // This is only indicative of how many times SurfaceFlinger posts 725 // frames to the display. 726 CALC_FPS(); 727 MDPComp::resetIdleFallBack(); 728 ctx->mVideoTransFlag = false; 729 //Was locked at the beginning of prepare 730 ctx->mDrawLock.unlock(); 731 return ret; 732} 733 734int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp, 735 uint32_t* configs, size_t* numConfigs) { 736 int ret = 0; 737 hwc_context_t* ctx = (hwc_context_t*)(dev); 738 disp = getDpyforExternalDisplay(ctx, disp); 739 //in 1.1 there is no way to choose a config, report as config id # 0 740 //This config is passed to getDisplayAttributes. Ignore for now. 741 switch(disp) { 742 case HWC_DISPLAY_PRIMARY: 743 if(*numConfigs > 0) { 744 configs[0] = 0; 745 *numConfigs = 1; 746 } 747 ret = 0; //NO_ERROR 748 break; 749 case HWC_DISPLAY_EXTERNAL: 750 case HWC_DISPLAY_VIRTUAL: 751 ret = -1; //Not connected 752 if(ctx->dpyAttr[disp].connected) { 753 ret = 0; //NO_ERROR 754 if(*numConfigs > 0) { 755 configs[0] = 0; 756 *numConfigs = 1; 757 } 758 } 759 break; 760 } 761 return ret; 762} 763 764int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp, 765 uint32_t /*config*/, const uint32_t* attributes, int32_t* values) { 766 767 hwc_context_t* ctx = (hwc_context_t*)(dev); 768 disp = getDpyforExternalDisplay(ctx, disp); 769 //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error 770 if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) { 771 return -1; 772 } 773 774 //From HWComposer 775 static const uint32_t DISPLAY_ATTRIBUTES[] = { 776 HWC_DISPLAY_VSYNC_PERIOD, 777 HWC_DISPLAY_WIDTH, 778 HWC_DISPLAY_HEIGHT, 779 HWC_DISPLAY_DPI_X, 780 HWC_DISPLAY_DPI_Y, 781 HWC_DISPLAY_NO_ATTRIBUTE, 782 }; 783 784 const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) / 785 sizeof(DISPLAY_ATTRIBUTES)[0]); 786 787 for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) { 788 switch (attributes[i]) { 789 case HWC_DISPLAY_VSYNC_PERIOD: 790 values[i] = ctx->dpyAttr[disp].vsync_period; 791 break; 792 case HWC_DISPLAY_WIDTH: 793 if (ctx->dpyAttr[disp].customFBSize) 794 values[i] = ctx->dpyAttr[disp].xres_new; 795 else 796 values[i] = ctx->dpyAttr[disp].xres; 797 798 ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp, 799 values[i]); 800 break; 801 case HWC_DISPLAY_HEIGHT: 802 if (ctx->dpyAttr[disp].customFBSize) 803 values[i] = ctx->dpyAttr[disp].yres_new; 804 else 805 values[i] = ctx->dpyAttr[disp].yres; 806 ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp, 807 values[i]); 808 break; 809 case HWC_DISPLAY_DPI_X: 810 values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0); 811 break; 812 case HWC_DISPLAY_DPI_Y: 813 values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0); 814 break; 815 default: 816 ALOGE("Unknown display attribute %d", 817 attributes[i]); 818 return -EINVAL; 819 } 820 } 821 return 0; 822} 823 824void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len) 825{ 826 hwc_context_t* ctx = (hwc_context_t*)(dev); 827 Locker::Autolock _l(ctx->mDrawLock); 828 android::String8 aBuf(""); 829 dumpsys_log(aBuf, "Qualcomm HWC state:\n"); 830 dumpsys_log(aBuf, " MDPVersion=%d\n", ctx->mMDP.version); 831 dumpsys_log(aBuf, " DisplayPanel=%c\n", ctx->mMDP.panel); 832 if(ctx->vstate.fakevsync) 833 dumpsys_log(aBuf, " Vsync is being faked!!\n"); 834 for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) { 835 if(ctx->mMDPComp[dpy]) 836 ctx->mMDPComp[dpy]->dump(aBuf); 837 } 838 char ovDump[2048] = {'\0'}; 839 ctx->mOverlay->getDump(ovDump, 2048); 840 dumpsys_log(aBuf, ovDump); 841 ovDump[0] = '\0'; 842 ctx->mRotMgr->getDump(ovDump, 1024); 843 dumpsys_log(aBuf, ovDump); 844 ovDump[0] = '\0'; 845 if(Writeback::getDump(ovDump, 1024)) { 846 dumpsys_log(aBuf, ovDump); 847 ovDump[0] = '\0'; 848 } 849 strlcpy(buff, aBuf.string(), buff_len); 850} 851 852static int hwc_device_close(struct hw_device_t *dev) 853{ 854 if(!dev) { 855 ALOGE("%s: NULL device pointer", __FUNCTION__); 856 return -1; 857 } 858 closeContext((hwc_context_t*)dev); 859 free(dev); 860 861 return 0; 862} 863 864static int hwc_device_open(const struct hw_module_t* module, const char* name, 865 struct hw_device_t** device) 866{ 867 int status = -EINVAL; 868 869 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 870 struct hwc_context_t *dev; 871 dev = (hwc_context_t*)malloc(sizeof(*dev)); 872 if(dev == NULL) 873 return status; 874 memset(dev, 0, sizeof(*dev)); 875 876 //Initialize hwc context 877 initContext(dev); 878 879 //Setup HWC methods 880 dev->device.common.tag = HARDWARE_DEVICE_TAG; 881 dev->device.common.version = HWC_DEVICE_API_VERSION_1_3; 882 dev->device.common.module = const_cast<hw_module_t*>(module); 883 dev->device.common.close = hwc_device_close; 884 dev->device.prepare = hwc_prepare; 885 dev->device.set = hwc_set; 886 dev->device.eventControl = hwc_eventControl; 887 dev->device.blank = hwc_blank; 888 dev->device.query = hwc_query; 889 dev->device.registerProcs = hwc_registerProcs; 890 dev->device.dump = hwc_dump; 891 dev->device.getDisplayConfigs = hwc_getDisplayConfigs; 892 dev->device.getDisplayAttributes = hwc_getDisplayAttributes; 893 *device = &dev->device.common; 894 status = 0; 895 } 896 return status; 897} 898