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