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