1 /* 2 * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved. 3 * Not a Contribution, Apache license notifications and license are retained 4 * for attribution purposes only. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #include <math.h> 20 #include "hwc_mdpcomp.h" 21 #include <sys/ioctl.h> 22 #include "external.h" 23 #include "qdMetaData.h" 24 #include "mdp_version.h" 25 #include <overlayRotator.h> 26 27 using overlay::Rotator; 28 using namespace overlay::utils; 29 namespace ovutils = overlay::utils; 30 31 namespace qhwc { 32 33 //==============MDPComp======================================================== 34 35 IdleInvalidator *MDPComp::idleInvalidator = NULL; 36 bool MDPComp::sIdleFallBack = false; 37 bool MDPComp::sDebugLogs = false; 38 bool MDPComp::sEnabled = false; 39 int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER; 40 41 MDPComp* MDPComp::getObject(const int& width, int dpy) { 42 if(width <= MAX_DISPLAY_DIM) { 43 return new MDPCompLowRes(dpy); 44 } else { 45 return new MDPCompHighRes(dpy); 46 } 47 } 48 49 MDPComp::MDPComp(int dpy):mDpy(dpy){}; 50 51 void MDPComp::dump(android::String8& buf) 52 { 53 dumpsys_log(buf,"HWC Map for Dpy: %s \n", 54 mDpy ? "\"EXTERNAL\"" : "\"PRIMARY\""); 55 dumpsys_log(buf,"PREV_FRAME: layerCount:%2d mdpCount:%2d \ 56 cacheCount:%2d \n", mCachedFrame.layerCount, 57 mCachedFrame.mdpCount, mCachedFrame.cacheCount); 58 dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d \ 59 fbCount:%2d \n", mCurrentFrame.layerCount, 60 mCurrentFrame.mdpCount, mCurrentFrame.fbCount); 61 dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n", 62 (mCurrentFrame.needsRedraw? "YES" : "NO"), 63 mCurrentFrame.mdpCount, sMaxPipesPerMixer); 64 dumpsys_log(buf," --------------------------------------------- \n"); 65 dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n"); 66 dumpsys_log(buf," --------------------------------------------- \n"); 67 for(int index = 0; index < mCurrentFrame.layerCount; index++ ) 68 dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n", 69 index, 70 (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"), 71 mCurrentFrame.layerToMDP[index], 72 (mCurrentFrame.isFBComposed[index] ? 73 (mCurrentFrame.needsRedraw ? "GLES" : "CACHE") : "MDP"), 74 (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ : 75 mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder)); 76 dumpsys_log(buf,"\n"); 77 } 78 79 bool MDPComp::init(hwc_context_t *ctx) { 80 81 if(!ctx) { 82 ALOGE("%s: Invalid hwc context!!",__FUNCTION__); 83 return false; 84 } 85 86 char property[PROPERTY_VALUE_MAX]; 87 88 sEnabled = false; 89 if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) && 90 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) || 91 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) { 92 sEnabled = true; 93 } 94 95 sDebugLogs = false; 96 if(property_get("debug.mdpcomp.logs", property, NULL) > 0) { 97 if(atoi(property) != 0) 98 sDebugLogs = true; 99 } 100 101 sMaxPipesPerMixer = MAX_PIPES_PER_MIXER; 102 if(property_get("debug.mdpcomp.maxpermixer", property, NULL) > 0) { 103 if(atoi(property) != 0) 104 sMaxPipesPerMixer = true; 105 } 106 107 unsigned long idle_timeout = DEFAULT_IDLE_TIME; 108 if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) { 109 if(atoi(property) != 0) 110 idle_timeout = atoi(property); 111 } 112 113 //create Idle Invalidator 114 idleInvalidator = IdleInvalidator::getInstance(); 115 116 if(idleInvalidator == NULL) { 117 ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__); 118 } else { 119 idleInvalidator->init(timeout_handler, ctx, idle_timeout); 120 } 121 return true; 122 } 123 124 void MDPComp::timeout_handler(void *udata) { 125 struct hwc_context_t* ctx = (struct hwc_context_t*)(udata); 126 127 if(!ctx) { 128 ALOGE("%s: received empty data in timer callback", __FUNCTION__); 129 return; 130 } 131 132 if(!ctx->proc) { 133 ALOGE("%s: HWC proc not registered", __FUNCTION__); 134 return; 135 } 136 sIdleFallBack = true; 137 /* Trigger SF to redraw the current frame */ 138 ctx->proc->invalidate(ctx->proc); 139 } 140 141 void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx, 142 hwc_display_contents_1_t* list) { 143 LayerProp *layerProp = ctx->layerProp[mDpy]; 144 145 for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) { 146 hwc_layer_1_t* layer = &(list->hwLayers[index]); 147 if(!mCurrentFrame.isFBComposed[index]) { 148 layerProp[index].mFlags |= HWC_MDPCOMP; 149 layer->compositionType = HWC_OVERLAY; 150 layer->hints |= HWC_HINT_CLEAR_FB; 151 mCachedFrame.hnd[index] = NULL; 152 } else { 153 if(!mCurrentFrame.needsRedraw) 154 layer->compositionType = HWC_OVERLAY; 155 } 156 } 157 } 158 159 /* 160 * Sets up BORDERFILL as default base pipe and detaches RGB0. 161 * Framebuffer is always updated using PLAY ioctl. 162 */ 163 bool MDPComp::setupBasePipe(hwc_context_t *ctx) { 164 const int dpy = HWC_DISPLAY_PRIMARY; 165 int fb_stride = ctx->dpyAttr[dpy].stride; 166 int fb_width = ctx->dpyAttr[dpy].xres; 167 int fb_height = ctx->dpyAttr[dpy].yres; 168 int fb_fd = ctx->dpyAttr[dpy].fd; 169 170 mdp_overlay ovInfo; 171 msmfb_overlay_data ovData; 172 memset(&ovInfo, 0, sizeof(mdp_overlay)); 173 memset(&ovData, 0, sizeof(msmfb_overlay_data)); 174 175 ovInfo.src.format = MDP_RGB_BORDERFILL; 176 ovInfo.src.width = fb_width; 177 ovInfo.src.height = fb_height; 178 ovInfo.src_rect.w = fb_width; 179 ovInfo.src_rect.h = fb_height; 180 ovInfo.dst_rect.w = fb_width; 181 ovInfo.dst_rect.h = fb_height; 182 ovInfo.id = MSMFB_NEW_REQUEST; 183 184 if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) { 185 ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s", 186 strerror(errno)); 187 return false; 188 } 189 190 ovData.id = ovInfo.id; 191 if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) { 192 ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s", 193 strerror(errno)); 194 return false; 195 } 196 return true; 197 } 198 199 MDPComp::FrameInfo::FrameInfo() { 200 reset(0); 201 } 202 203 void MDPComp::FrameInfo::reset(const int& numLayers) { 204 for(int i = 0 ; i < MAX_PIPES_PER_MIXER && numLayers; i++ ) { 205 if(mdpToLayer[i].pipeInfo) { 206 delete mdpToLayer[i].pipeInfo; 207 mdpToLayer[i].pipeInfo = NULL; 208 //We dont own the rotator 209 mdpToLayer[i].rot = NULL; 210 } 211 } 212 213 memset(&mdpToLayer, 0, sizeof(mdpToLayer)); 214 memset(&layerToMDP, -1, sizeof(layerToMDP)); 215 memset(&isFBComposed, 1, sizeof(isFBComposed)); 216 217 layerCount = numLayers; 218 fbCount = numLayers; 219 mdpCount = 0; 220 needsRedraw = true; 221 fbZ = 0; 222 } 223 224 void MDPComp::FrameInfo::map() { 225 // populate layer and MDP maps 226 int mdpIdx = 0; 227 for(int idx = 0; idx < layerCount; idx++) { 228 if(!isFBComposed[idx]) { 229 mdpToLayer[mdpIdx].listIndex = idx; 230 layerToMDP[idx] = mdpIdx++; 231 } 232 } 233 } 234 235 MDPComp::LayerCache::LayerCache() { 236 reset(); 237 } 238 239 void MDPComp::LayerCache::reset() { 240 memset(&hnd, 0, sizeof(hnd)); 241 mdpCount = 0; 242 cacheCount = 0; 243 layerCount = 0; 244 fbZ = -1; 245 } 246 247 void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) { 248 const int numAppLayers = list->numHwLayers - 1; 249 for(int i = 0; i < numAppLayers; i++) { 250 hnd[i] = list->hwLayers[i].handle; 251 } 252 } 253 254 void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) { 255 mdpCount = curFrame.mdpCount; 256 cacheCount = curFrame.fbCount; 257 layerCount = curFrame.layerCount; 258 fbZ = curFrame.fbZ; 259 } 260 261 bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) { 262 const int dpy = HWC_DISPLAY_PRIMARY; 263 private_handle_t *hnd = (private_handle_t *)layer->handle; 264 265 if(!hnd) { 266 ALOGE("%s: layer handle is NULL", __FUNCTION__); 267 return false; 268 } 269 270 int hw_w = ctx->dpyAttr[mDpy].xres; 271 int hw_h = ctx->dpyAttr[mDpy].yres; 272 273 hwc_rect_t crop = layer->sourceCrop; 274 hwc_rect_t dst = layer->displayFrame; 275 276 if(dst.left < 0 || dst.top < 0 || dst.right > hw_w || dst.bottom > hw_h) { 277 hwc_rect_t scissor = {0, 0, hw_w, hw_h }; 278 qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform); 279 } 280 281 int crop_w = crop.right - crop.left; 282 int crop_h = crop.bottom - crop.top; 283 int dst_w = dst.right - dst.left; 284 int dst_h = dst.bottom - dst.top; 285 float w_dscale = ceilf((float)crop_w / (float)dst_w); 286 float h_dscale = ceilf((float)crop_h / (float)dst_h); 287 288 //Workaround for MDP HW limitation in DSI command mode panels where 289 //FPS will not go beyond 30 if buffers on RGB pipes are of width < 5 290 291 if((crop_w < 5)||(crop_h < 5)) 292 return false; 293 294 if(ctx->mMDP.version >= qdutils::MDSS_V5) { 295 /* Workaround for downscales larger than 4x. 296 * Will be removed once decimator block is enabled for MDSS 297 */ 298 if(w_dscale > 4.0f || h_dscale > 4.0f) 299 return false; 300 } else { 301 if(w_dscale > 8.0f || h_dscale > 8.0f) 302 // MDP 4 supports 1/8 downscale 303 return false; 304 } 305 306 return true; 307 } 308 309 ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type) { 310 overlay::Overlay& ov = *ctx->mOverlay; 311 ovutils::eDest mdp_pipe = ovutils::OV_INVALID; 312 313 switch(type) { 314 case MDPCOMP_OV_DMA: 315 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, mDpy); 316 if(mdp_pipe != ovutils::OV_INVALID) { 317 ctx->mDMAInUse = true; 318 return mdp_pipe; 319 } 320 case MDPCOMP_OV_ANY: 321 case MDPCOMP_OV_RGB: 322 mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy); 323 if(mdp_pipe != ovutils::OV_INVALID) { 324 return mdp_pipe; 325 } 326 327 if(type == MDPCOMP_OV_RGB) { 328 //Requested only for RGB pipe 329 break; 330 } 331 case MDPCOMP_OV_VG: 332 return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy); 333 default: 334 ALOGE("%s: Invalid pipe type",__FUNCTION__); 335 return ovutils::OV_INVALID; 336 }; 337 return ovutils::OV_INVALID; 338 } 339 340 bool MDPComp::isFrameDoable(hwc_context_t *ctx) { 341 int numAppLayers = ctx->listStats[mDpy].numAppLayers; 342 bool ret = true; 343 344 if(!isEnabled()) { 345 ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__); 346 ret = false; 347 } else if(ctx->mExtDispConfiguring) { 348 ALOGD_IF( isDebug(),"%s: External Display connection is pending", 349 __FUNCTION__); 350 ret = false; 351 } 352 return ret; 353 } 354 355 /* Checks for conditions where all the layers marked for MDP comp cannot be 356 * bypassed. On such conditions we try to bypass atleast YUV layers */ 357 bool MDPComp::isFullFrameDoable(hwc_context_t *ctx, 358 hwc_display_contents_1_t* list){ 359 360 const int numAppLayers = ctx->listStats[mDpy].numAppLayers; 361 362 if(sIdleFallBack) { 363 ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy); 364 return false; 365 } 366 367 if(mDpy > HWC_DISPLAY_PRIMARY){ 368 ALOGD_IF(isDebug(), "%s: Cannot support External display(s)", 369 __FUNCTION__); 370 return false; 371 } 372 373 if(isSkipPresent(ctx, mDpy)) { 374 ALOGD_IF(isDebug(),"%s: SKIP present: %d", 375 __FUNCTION__, 376 isSkipPresent(ctx, mDpy)); 377 return false; 378 } 379 380 if(ctx->listStats[mDpy].planeAlpha 381 && ctx->mMDP.version >= qdutils::MDSS_V5) { 382 ALOGD_IF(isDebug(), "%s: plane alpha not implemented on MDSS", 383 __FUNCTION__); 384 return false; 385 } 386 387 if(ctx->listStats[mDpy].needsAlphaScale 388 && ctx->mMDP.version < qdutils::MDSS_V5) { 389 ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__); 390 return false; 391 } 392 393 //MDP composition is not efficient if layer needs rotator. 394 for(int i = 0; i < numAppLayers; ++i) { 395 // As MDP h/w supports flip operation, use MDP comp only for 396 // 180 transforms. Fail for any transform involving 90 (90, 270). 397 hwc_layer_1_t* layer = &list->hwLayers[i]; 398 private_handle_t *hnd = (private_handle_t *)layer->handle; 399 if(isYuvBuffer(hnd) ) { 400 if(isSecuring(ctx, layer)) { 401 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__); 402 return false; 403 } 404 } else if(layer->transform & HWC_TRANSFORM_ROT_90) { 405 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__); 406 return false; 407 } 408 409 if(!isValidDimension(ctx,layer)) { 410 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width", 411 __FUNCTION__); 412 return false; 413 } 414 } 415 416 //If all above hard conditions are met we can do full or partial MDP comp. 417 bool ret = false; 418 if(fullMDPComp(ctx, list)) { 419 ret = true; 420 } else if (partialMDPComp(ctx, list)) { 421 ret = true; 422 } 423 return ret; 424 } 425 426 bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 427 //Setup mCurrentFrame 428 mCurrentFrame.mdpCount = mCurrentFrame.layerCount; 429 mCurrentFrame.fbCount = 0; 430 mCurrentFrame.fbZ = -1; 431 memset(&mCurrentFrame.isFBComposed, 0, sizeof(mCurrentFrame.isFBComposed)); 432 433 int mdpCount = mCurrentFrame.mdpCount; 434 if(mdpCount > sMaxPipesPerMixer) { 435 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__); 436 return false; 437 } 438 439 int numPipesNeeded = pipesNeeded(ctx, list); 440 int availPipes = getAvailablePipes(ctx); 441 442 if(numPipesNeeded > availPipes) { 443 ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d", 444 __FUNCTION__, numPipesNeeded, availPipes); 445 return false; 446 } 447 448 return true; 449 } 450 451 bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) 452 { 453 int numAppLayers = ctx->listStats[mDpy].numAppLayers; 454 //Setup mCurrentFrame 455 mCurrentFrame.reset(numAppLayers); 456 updateLayerCache(ctx, list); 457 updateYUV(ctx, list); 458 batchLayers(); //sets up fbZ also 459 460 int mdpCount = mCurrentFrame.mdpCount; 461 if(mdpCount > (sMaxPipesPerMixer - 1)) { // -1 since FB is used 462 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__); 463 return false; 464 } 465 466 int numPipesNeeded = pipesNeeded(ctx, list); 467 int availPipes = getAvailablePipes(ctx); 468 469 if(numPipesNeeded > availPipes) { 470 ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d", 471 __FUNCTION__, numPipesNeeded, availPipes); 472 return false; 473 } 474 475 return true; 476 } 477 478 bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx, 479 hwc_display_contents_1_t* list){ 480 int numAppLayers = ctx->listStats[mDpy].numAppLayers; 481 mCurrentFrame.reset(numAppLayers); 482 updateYUV(ctx, list); 483 int mdpCount = mCurrentFrame.mdpCount; 484 int fbNeeded = int(mCurrentFrame.fbCount != 0); 485 486 if(!isYuvPresent(ctx, mDpy)) { 487 return false; 488 } 489 490 if(!mdpCount) 491 return false; 492 493 if(mdpCount > (sMaxPipesPerMixer - fbNeeded)) { 494 ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__); 495 return false; 496 } 497 498 int numPipesNeeded = pipesNeeded(ctx, list); 499 int availPipes = getAvailablePipes(ctx); 500 if(numPipesNeeded > availPipes) { 501 ALOGD_IF(isDebug(), "%s: Insufficient MDP pipes, needed %d, avail %d", 502 __FUNCTION__, numPipesNeeded, availPipes); 503 return false; 504 } 505 506 return true; 507 } 508 509 /* Checks for conditions where YUV layers cannot be bypassed */ 510 bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) { 511 512 if(isSkipLayer(layer)) { 513 ALOGE("%s: Unable to bypass skipped YUV", __FUNCTION__); 514 return false; 515 } 516 517 if(layer->planeAlpha < 0xFF) { 518 ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha", 519 __FUNCTION__); 520 return false; 521 } 522 523 if(ctx->mNeedsRotator && ctx->mDMAInUse) { 524 ALOGE("%s: No DMA for Rotator",__FUNCTION__); 525 return false; 526 } 527 528 if(isSecuring(ctx, layer)) { 529 ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__); 530 return false; 531 } 532 533 if(!isValidDimension(ctx, layer)) { 534 ALOGD_IF(isDebug(), "%s: Buffer is of invalid width", 535 __FUNCTION__); 536 return false; 537 } 538 539 return true; 540 } 541 542 void MDPComp::batchLayers() { 543 /* Idea is to keep as many contiguous non-updating(cached) layers in FB and 544 * send rest of them through MDP. NEVER mark an updating layer for caching. 545 * But cached ones can be marked for MDP*/ 546 547 int maxBatchStart = -1; 548 int maxBatchCount = 0; 549 550 /* All or Nothing is cached. No batching needed */ 551 if(!mCurrentFrame.fbCount) { 552 mCurrentFrame.fbZ = -1; 553 return; 554 } 555 if(!mCurrentFrame.mdpCount) { 556 mCurrentFrame.fbZ = 0; 557 return; 558 } 559 560 /* Search for max number of contiguous (cached) layers */ 561 int i = 0; 562 while (i < mCurrentFrame.layerCount) { 563 int count = 0; 564 while(mCurrentFrame.isFBComposed[i] && i < mCurrentFrame.layerCount) { 565 count++; i++; 566 } 567 if(count > maxBatchCount) { 568 maxBatchCount = count; 569 maxBatchStart = i - count; 570 mCurrentFrame.fbZ = maxBatchStart; 571 } 572 if(i < mCurrentFrame.layerCount) i++; 573 } 574 575 /* reset rest of the layers for MDP comp */ 576 for(int i = 0; i < mCurrentFrame.layerCount; i++) { 577 if(i != maxBatchStart){ 578 mCurrentFrame.isFBComposed[i] = false; 579 } else { 580 i += maxBatchCount; 581 } 582 } 583 584 mCurrentFrame.fbCount = maxBatchCount; 585 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - 586 mCurrentFrame.fbCount; 587 588 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__, 589 mCurrentFrame.fbCount); 590 } 591 592 void MDPComp::updateLayerCache(hwc_context_t* ctx, 593 hwc_display_contents_1_t* list) { 594 595 int numAppLayers = ctx->listStats[mDpy].numAppLayers; 596 int numCacheableLayers = 0; 597 598 for(int i = 0; i < numAppLayers; i++) { 599 if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) { 600 numCacheableLayers++; 601 mCurrentFrame.isFBComposed[i] = true; 602 } else { 603 mCurrentFrame.isFBComposed[i] = false; 604 mCachedFrame.hnd[i] = list->hwLayers[i].handle; 605 } 606 } 607 608 mCurrentFrame.fbCount = numCacheableLayers; 609 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - 610 mCurrentFrame.fbCount; 611 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__, numCacheableLayers); 612 } 613 614 int MDPComp::getAvailablePipes(hwc_context_t* ctx) { 615 int numDMAPipes = qdutils::MDPVersion::getInstance().getDMAPipes(); 616 overlay::Overlay& ov = *ctx->mOverlay; 617 618 int numAvailable = ov.availablePipes(mDpy); 619 620 //Reserve DMA for rotator 621 if(ctx->mNeedsRotator) 622 numAvailable -= numDMAPipes; 623 624 //Reserve pipe(s)for FB 625 if(mCurrentFrame.fbCount) 626 numAvailable -= pipesForFB(); 627 628 return numAvailable; 629 } 630 631 void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list) { 632 633 int nYuvCount = ctx->listStats[mDpy].yuvCount; 634 for(int index = 0;index < nYuvCount; index++){ 635 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index]; 636 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex]; 637 638 if(!isYUVDoable(ctx, layer)) { 639 if(!mCurrentFrame.isFBComposed[nYuvIndex]) { 640 mCurrentFrame.isFBComposed[nYuvIndex] = true; 641 mCurrentFrame.fbCount++; 642 } 643 } else { 644 if(mCurrentFrame.isFBComposed[nYuvIndex]) { 645 mCurrentFrame.isFBComposed[nYuvIndex] = false; 646 mCurrentFrame.fbCount--; 647 } 648 } 649 } 650 651 mCurrentFrame.mdpCount = mCurrentFrame.layerCount - 652 mCurrentFrame.fbCount; 653 ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__, 654 mCurrentFrame.fbCount); 655 } 656 657 bool MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 658 ctx->mDMAInUse = false; 659 if(!allocLayerPipes(ctx, list)) { 660 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__); 661 return false; 662 } 663 664 bool fbBatch = false; 665 for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount; 666 index++) { 667 if(!mCurrentFrame.isFBComposed[index]) { 668 int mdpIndex = mCurrentFrame.layerToMDP[index]; 669 hwc_layer_1_t* layer = &list->hwLayers[index]; 670 671 MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo; 672 cur_pipe->zOrder = mdpNextZOrder++; 673 674 if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){ 675 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \ 676 layer %d",__FUNCTION__, index); 677 return false; 678 } 679 } else if(fbBatch == false) { 680 mdpNextZOrder++; 681 fbBatch = true; 682 } 683 } 684 685 return true; 686 } 687 688 bool MDPComp::programYUV(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 689 if(!allocLayerPipes(ctx, list)) { 690 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__); 691 return false; 692 } 693 //If we are in this block, it means we have yuv + rgb layers both 694 int mdpIdx = 0; 695 for (int index = 0; index < mCurrentFrame.layerCount; index++) { 696 if(!mCurrentFrame.isFBComposed[index]) { 697 hwc_layer_1_t* layer = &list->hwLayers[index]; 698 int mdpIndex = mCurrentFrame.layerToMDP[index]; 699 MdpPipeInfo* cur_pipe = 700 mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo; 701 cur_pipe->zOrder = mdpIdx++; 702 703 if(configure(ctx, layer, 704 mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){ 705 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \ 706 layer %d",__FUNCTION__, index); 707 return false; 708 } 709 } 710 } 711 return true; 712 } 713 714 int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 715 716 //reset old data 717 const int numLayers = ctx->listStats[mDpy].numAppLayers; 718 mCurrentFrame.reset(numLayers); 719 720 //Hard conditions, if not met, cannot do MDP comp 721 if(!isFrameDoable(ctx)) { 722 ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame", 723 __FUNCTION__); 724 mCurrentFrame.reset(numLayers); 725 mCachedFrame.cacheAll(list); 726 mCachedFrame.updateCounts(mCurrentFrame); 727 return 0; 728 } 729 730 //Check whether layers marked for MDP Composition is actually doable. 731 if(isFullFrameDoable(ctx, list)){ 732 mCurrentFrame.map(); 733 //Acquire and Program MDP pipes 734 if(!programMDP(ctx, list)) { 735 mCurrentFrame.reset(numLayers); 736 mCachedFrame.cacheAll(list); 737 } else { //Success 738 //Any change in composition types needs an FB refresh 739 mCurrentFrame.needsRedraw = false; 740 if(mCurrentFrame.fbCount && 741 ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) || 742 (mCurrentFrame.fbCount != mCachedFrame.cacheCount) || 743 (mCurrentFrame.fbZ != mCachedFrame.fbZ) || 744 (!mCurrentFrame.mdpCount) || 745 (list->flags & HWC_GEOMETRY_CHANGED) || 746 isSkipPresent(ctx, mDpy) || 747 (mDpy > HWC_DISPLAY_PRIMARY))) { 748 mCurrentFrame.needsRedraw = true; 749 } 750 } 751 } else if(isOnlyVideoDoable(ctx, list)) { 752 //All layers marked for MDP comp cannot be bypassed. 753 //Try to compose atleast YUV layers through MDP comp and let 754 //all the RGB layers compose in FB 755 //Destination over 756 mCurrentFrame.fbZ = -1; 757 if(mCurrentFrame.fbCount) 758 mCurrentFrame.fbZ = ctx->listStats[mDpy].yuvCount; 759 760 mCurrentFrame.map(); 761 if(!programYUV(ctx, list)) { 762 mCurrentFrame.reset(numLayers); 763 mCachedFrame.cacheAll(list); 764 } 765 } else { 766 mCurrentFrame.reset(numLayers); 767 mCachedFrame.cacheAll(list); 768 } 769 770 //UpdateLayerFlags 771 setMDPCompLayerFlags(ctx, list); 772 mCachedFrame.updateCounts(mCurrentFrame); 773 774 if(isDebug()) { 775 ALOGD("GEOMETRY change: %d", (list->flags & HWC_GEOMETRY_CHANGED)); 776 android::String8 sDump(""); 777 dump(sDump); 778 ALOGE("%s",sDump.string()); 779 } 780 781 return mCurrentFrame.fbZ; 782 } 783 784 //=============MDPCompLowRes=================================================== 785 786 /* 787 * Configures pipe(s) for MDP composition 788 */ 789 int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, 790 PipeLayerPair& PipeLayerPair) { 791 MdpPipeInfoLowRes& mdp_info = 792 *(static_cast<MdpPipeInfoLowRes*>(PipeLayerPair.pipeInfo)); 793 eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION; 794 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder); 795 eIsFg isFg = IS_FG_OFF; 796 eDest dest = mdp_info.index; 797 798 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d", 799 __FUNCTION__, layer, zOrder, dest); 800 801 return configureLowRes(ctx, layer, mDpy, mdpFlags, zOrder, isFg, dest, 802 &PipeLayerPair.rot); 803 } 804 805 int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx, 806 hwc_display_contents_1_t* list) { 807 return mCurrentFrame.mdpCount; 808 } 809 810 bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx, 811 hwc_display_contents_1_t* list) { 812 if(isYuvPresent(ctx, mDpy)) { 813 int nYuvCount = ctx->listStats[mDpy].yuvCount; 814 815 for(int index = 0; index < nYuvCount ; index ++) { 816 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index]; 817 818 if(mCurrentFrame.isFBComposed[nYuvIndex]) 819 continue; 820 821 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex]; 822 823 int mdpIndex = mCurrentFrame.layerToMDP[nYuvIndex]; 824 825 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex]; 826 info.pipeInfo = new MdpPipeInfoLowRes; 827 info.rot = NULL; 828 MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo; 829 830 pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG); 831 if(pipe_info.index == ovutils::OV_INVALID) { 832 ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos", 833 __FUNCTION__); 834 return false; 835 } 836 } 837 } 838 839 for(int index = 0 ; index < mCurrentFrame.layerCount; index++ ) { 840 if(mCurrentFrame.isFBComposed[index]) continue; 841 hwc_layer_1_t* layer = &list->hwLayers[index]; 842 private_handle_t *hnd = (private_handle_t *)layer->handle; 843 844 if(isYuvBuffer(hnd)) 845 continue; 846 847 int mdpIndex = mCurrentFrame.layerToMDP[index]; 848 849 PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex]; 850 info.pipeInfo = new MdpPipeInfoLowRes; 851 info.rot = NULL; 852 MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo; 853 854 ePipeType type = MDPCOMP_OV_ANY; 855 856 if(!qhwc::needsScaling(layer) && !ctx->mNeedsRotator 857 && ctx->mMDP.version >= qdutils::MDSS_V5) { 858 type = MDPCOMP_OV_DMA; 859 } 860 861 pipe_info.index = getMdpPipe(ctx, type); 862 if(pipe_info.index == ovutils::OV_INVALID) { 863 ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__); 864 return false; 865 } 866 } 867 return true; 868 } 869 870 bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 871 872 if(!isEnabled()) { 873 ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__); 874 return true; 875 } 876 877 if(!ctx || !list) { 878 ALOGE("%s: invalid contxt or list",__FUNCTION__); 879 return false; 880 } 881 882 /* reset Invalidator */ 883 if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount) 884 idleInvalidator->markForSleep(); 885 886 overlay::Overlay& ov = *ctx->mOverlay; 887 LayerProp *layerProp = ctx->layerProp[mDpy]; 888 889 int numHwLayers = ctx->listStats[mDpy].numAppLayers; 890 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ ) 891 { 892 if(mCurrentFrame.isFBComposed[i]) continue; 893 894 hwc_layer_1_t *layer = &list->hwLayers[i]; 895 private_handle_t *hnd = (private_handle_t *)layer->handle; 896 if(!hnd) { 897 ALOGE("%s handle null", __FUNCTION__); 898 return false; 899 } 900 901 int mdpIndex = mCurrentFrame.layerToMDP[i]; 902 903 MdpPipeInfoLowRes& pipe_info = 904 *(MdpPipeInfoLowRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo; 905 ovutils::eDest dest = pipe_info.index; 906 if(dest == ovutils::OV_INVALID) { 907 ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest); 908 return false; 909 } 910 911 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) { 912 continue; 913 } 914 915 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ 916 using pipe: %d", __FUNCTION__, layer, 917 hnd, dest ); 918 919 int fd = hnd->fd; 920 uint32_t offset = hnd->offset; 921 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot; 922 if(rot) { 923 if(!rot->queueBuffer(fd, offset)) 924 return false; 925 fd = rot->getDstMemId(); 926 offset = rot->getDstOffset(); 927 } 928 929 if (!ov.queueBuffer(fd, offset, dest)) { 930 ALOGE("%s: queueBuffer failed for external", __FUNCTION__); 931 return false; 932 } 933 934 layerProp[i].mFlags &= ~HWC_MDPCOMP; 935 } 936 return true; 937 } 938 939 //=============MDPCompHighRes=================================================== 940 941 int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx, 942 hwc_display_contents_1_t* list) { 943 int pipesNeeded = 0; 944 int hw_w = ctx->dpyAttr[mDpy].xres; 945 946 for(int i = 0; i < mCurrentFrame.layerCount; ++i) { 947 if(!mCurrentFrame.isFBComposed[i]) { 948 hwc_layer_1_t* layer = &list->hwLayers[i]; 949 hwc_rect_t dst = layer->displayFrame; 950 if(dst.left > hw_w/2) { 951 pipesNeeded++; 952 } else if(dst.right <= hw_w/2) { 953 pipesNeeded++; 954 } else { 955 pipesNeeded += 2; 956 } 957 } 958 } 959 return pipesNeeded; 960 } 961 962 bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer, 963 MdpPipeInfoHighRes& pipe_info, 964 ePipeType type) { 965 int hw_w = ctx->dpyAttr[mDpy].xres; 966 967 hwc_rect_t dst = layer->displayFrame; 968 if(dst.left > hw_w/2) { 969 pipe_info.lIndex = ovutils::OV_INVALID; 970 pipe_info.rIndex = getMdpPipe(ctx, type); 971 if(pipe_info.rIndex == ovutils::OV_INVALID) 972 return false; 973 } else if (dst.right <= hw_w/2) { 974 pipe_info.rIndex = ovutils::OV_INVALID; 975 pipe_info.lIndex = getMdpPipe(ctx, type); 976 if(pipe_info.lIndex == ovutils::OV_INVALID) 977 return false; 978 } else { 979 pipe_info.rIndex = getMdpPipe(ctx, type); 980 pipe_info.lIndex = getMdpPipe(ctx, type); 981 if(pipe_info.rIndex == ovutils::OV_INVALID || 982 pipe_info.lIndex == ovutils::OV_INVALID) 983 return false; 984 } 985 return true; 986 } 987 988 bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx, 989 hwc_display_contents_1_t* list) { 990 overlay::Overlay& ov = *ctx->mOverlay; 991 int layer_count = ctx->listStats[mDpy].numAppLayers; 992 993 if(isYuvPresent(ctx, mDpy)) { 994 int nYuvCount = ctx->listStats[mDpy].yuvCount; 995 996 for(int index = 0; index < nYuvCount; index ++) { 997 int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index]; 998 hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex]; 999 PipeLayerPair& info = mCurrentFrame.mdpToLayer[nYuvIndex]; 1000 info.pipeInfo = new MdpPipeInfoHighRes; 1001 info.rot = NULL; 1002 MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo; 1003 if(!acquireMDPPipes(ctx, layer, pipe_info,MDPCOMP_OV_VG)) { 1004 ALOGD_IF(isDebug(),"%s: Unable to get pipe for videos", 1005 __FUNCTION__); 1006 //TODO: windback pipebook data on fail 1007 return false; 1008 } 1009 pipe_info.zOrder = nYuvIndex; 1010 } 1011 } 1012 1013 for(int index = 0 ; index < layer_count ; index++ ) { 1014 hwc_layer_1_t* layer = &list->hwLayers[index]; 1015 private_handle_t *hnd = (private_handle_t *)layer->handle; 1016 1017 if(isYuvBuffer(hnd)) 1018 continue; 1019 1020 PipeLayerPair& info = mCurrentFrame.mdpToLayer[index]; 1021 info.pipeInfo = new MdpPipeInfoHighRes; 1022 info.rot = NULL; 1023 MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)info.pipeInfo; 1024 1025 ePipeType type = MDPCOMP_OV_ANY; 1026 1027 if(!qhwc::needsScaling(layer) && !ctx->mNeedsRotator 1028 && ctx->mMDP.version >= qdutils::MDSS_V5) 1029 type = MDPCOMP_OV_DMA; 1030 1031 if(!acquireMDPPipes(ctx, layer, pipe_info, type)) { 1032 ALOGD_IF(isDebug(), "%s: Unable to get pipe for UI", __FUNCTION__); 1033 //TODO: windback pipebook data on fail 1034 return false; 1035 } 1036 pipe_info.zOrder = index; 1037 } 1038 return true; 1039 } 1040 /* 1041 * Configures pipe(s) for MDP composition 1042 */ 1043 int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, 1044 PipeLayerPair& PipeLayerPair) { 1045 MdpPipeInfoHighRes& mdp_info = 1046 *(static_cast<MdpPipeInfoHighRes*>(PipeLayerPair.pipeInfo)); 1047 eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder); 1048 eIsFg isFg = IS_FG_OFF; 1049 eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION; 1050 eDest lDest = mdp_info.lIndex; 1051 eDest rDest = mdp_info.rIndex; 1052 1053 ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d" 1054 "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest); 1055 1056 return configureHighRes(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg, lDest, 1057 rDest, &PipeLayerPair.rot); 1058 } 1059 1060 bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 1061 1062 if(!isEnabled()) { 1063 ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__); 1064 return true; 1065 } 1066 1067 if(!ctx || !list) { 1068 ALOGE("%s: invalid contxt or list",__FUNCTION__); 1069 return false; 1070 } 1071 1072 /* reset Invalidator */ 1073 if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount) 1074 idleInvalidator->markForSleep(); 1075 1076 overlay::Overlay& ov = *ctx->mOverlay; 1077 LayerProp *layerProp = ctx->layerProp[mDpy]; 1078 1079 int numHwLayers = ctx->listStats[mDpy].numAppLayers; 1080 for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ ) 1081 { 1082 if(mCurrentFrame.isFBComposed[i]) continue; 1083 1084 hwc_layer_1_t *layer = &list->hwLayers[i]; 1085 private_handle_t *hnd = (private_handle_t *)layer->handle; 1086 if(!hnd) { 1087 ALOGE("%s handle null", __FUNCTION__); 1088 return false; 1089 } 1090 1091 if(!(layerProp[i].mFlags & HWC_MDPCOMP)) { 1092 continue; 1093 } 1094 1095 int mdpIndex = mCurrentFrame.layerToMDP[i]; 1096 1097 MdpPipeInfoHighRes& pipe_info = 1098 *(MdpPipeInfoHighRes*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo; 1099 Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot; 1100 1101 ovutils::eDest indexL = pipe_info.lIndex; 1102 ovutils::eDest indexR = pipe_info.rIndex; 1103 1104 int fd = hnd->fd; 1105 int offset = hnd->offset; 1106 1107 if(rot) { 1108 rot->queueBuffer(fd, offset); 1109 fd = rot->getDstMemId(); 1110 offset = rot->getDstOffset(); 1111 } 1112 1113 //************* play left mixer ********** 1114 if(indexL != ovutils::OV_INVALID) { 1115 ovutils::eDest destL = (ovutils::eDest)indexL; 1116 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ 1117 using pipe: %d", __FUNCTION__, layer, hnd, indexL ); 1118 if (!ov.queueBuffer(fd, offset, destL)) { 1119 ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__); 1120 return false; 1121 } 1122 } 1123 1124 //************* play right mixer ********** 1125 if(indexR != ovutils::OV_INVALID) { 1126 ovutils::eDest destR = (ovutils::eDest)indexR; 1127 ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ 1128 using pipe: %d", __FUNCTION__, layer, hnd, indexR ); 1129 if (!ov.queueBuffer(fd, offset, destR)) { 1130 ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__); 1131 return false; 1132 } 1133 } 1134 1135 layerProp[i].mFlags &= ~HWC_MDPCOMP; 1136 } 1137 1138 return true; 1139 } 1140 }; //namespace 1141 1142