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