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