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