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