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