1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved. 4 * 5 * Not a Contribution, Apache license notifications and license are 6 * retained for attribution purposes only. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21#define DEBUG_FBUPDATE 0 22#include <cutils/properties.h> 23#include <gralloc_priv.h> 24#include <overlay.h> 25#include <overlayRotator.h> 26#include "hwc_fbupdate.h" 27#include "mdp_version.h" 28#include "external.h" 29#include "virtual.h" 30 31using namespace qdutils; 32using namespace overlay; 33using overlay::Rotator; 34using namespace overlay::utils; 35 36namespace qhwc { 37 38namespace ovutils = overlay::utils; 39 40IFBUpdate* IFBUpdate::getObject(hwc_context_t *ctx, const int& dpy) { 41 if(qdutils::MDPVersion::getInstance().isSrcSplit()) { 42 return new FBSrcSplit(ctx, dpy); 43 } else if(isDisplaySplit(ctx, dpy)) { 44 return new FBUpdateSplit(ctx, dpy); 45 } 46 return new FBUpdateNonSplit(ctx, dpy); 47} 48 49IFBUpdate::IFBUpdate(hwc_context_t *ctx, const int& dpy) : mDpy(dpy) { 50 size_t size = 0; 51 getBufferAttributes(ctx->dpyAttr[mDpy].xres, 52 ctx->dpyAttr[mDpy].yres, 53 HAL_PIXEL_FORMAT_RGBA_8888, 54 0, 55 mAlignedFBWidth, 56 mAlignedFBHeight, 57 mTileEnabled, size); 58} 59 60void IFBUpdate::reset() { 61 mModeOn = false; 62 mRot = NULL; 63} 64 65bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx, 66 hwc_display_contents_1 *list, int fbZorder) { 67 hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1]; 68 mModeOn = prepare(ctx, list, layer->displayFrame, fbZorder) && 69 ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd); 70 return mModeOn; 71} 72 73//================= Low res==================================== 74FBUpdateNonSplit::FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy): 75 IFBUpdate(ctx, dpy) {} 76 77void FBUpdateNonSplit::reset() { 78 IFBUpdate::reset(); 79 mDest = ovutils::OV_INVALID; 80} 81 82bool FBUpdateNonSplit::preRotateExtDisplay(hwc_context_t *ctx, 83 hwc_layer_1_t *layer, 84 ovutils::Whf &info, 85 hwc_rect_t& sourceCrop, 86 ovutils::eMdpFlags& mdpFlags, 87 int& rotFlags) 88{ 89 int extOrient = getExtOrientation(ctx); 90 ovutils::eTransform orient = static_cast<ovutils::eTransform >(extOrient); 91 if(mDpy && (extOrient & HWC_TRANSFORM_ROT_90)) { 92 mRot = ctx->mRotMgr->getNext(); 93 if(mRot == NULL) return false; 94 ctx->mLayerRotMap[mDpy]->add(layer, mRot); 95 // Composed FB content will have black bars, if the viewFrame of the 96 // external is different from {0, 0, fbWidth, fbHeight}, so intersect 97 // viewFrame with sourceCrop to avoid those black bars 98 sourceCrop = getIntersection(sourceCrop, ctx->mViewFrame[mDpy]); 99 //Configure rotator for pre-rotation 100 if(configRotator(mRot, info, sourceCrop, mdpFlags, orient, 0) < 0) { 101 ALOGE("%s: configRotator Failed!", __FUNCTION__); 102 mRot = NULL; 103 return false; 104 } 105 info.format = (mRot)->getDstFormat(); 106 updateSource(orient, info, sourceCrop); 107 rotFlags |= ovutils::ROT_PREROTATED; 108 } 109 return true; 110} 111 112bool FBUpdateNonSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list, 113 hwc_rect_t fbUpdatingRect, int fbZorder) { 114 if(!ctx->mMDP.hasOverlay) { 115 ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays", 116 __FUNCTION__); 117 return false; 118 } 119 mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder); 120 return mModeOn; 121} 122 123// Configure 124bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list, 125 hwc_rect_t fbUpdatingRect, int fbZorder) { 126 bool ret = false; 127 hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1]; 128 if (LIKELY(ctx->mOverlay)) { 129 int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex; 130 // ext only layer present.. 131 if(extOnlyLayerIndex != -1) { 132 layer = &list->hwLayers[extOnlyLayerIndex]; 133 layer->compositionType = HWC_OVERLAY; 134 } 135 overlay::Overlay& ov = *(ctx->mOverlay); 136 137 ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight, 138 ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888, 139 mTileEnabled)); 140 141 Overlay::PipeSpecs pipeSpecs; 142 pipeSpecs.formatClass = Overlay::FORMAT_RGB; 143 pipeSpecs.needsScaling = qhwc::needsScaling(layer); 144 pipeSpecs.dpy = mDpy; 145 pipeSpecs.mixer = Overlay::MIXER_DEFAULT; 146 pipeSpecs.fb = true; 147 148 ovutils::eDest dest = ov.getPipe(pipeSpecs); 149 if(dest == ovutils::OV_INVALID) { //None available 150 ALOGE("%s: No pipes available to configure fb for dpy %d", 151 __FUNCTION__, mDpy); 152 return false; 153 } 154 mDest = dest; 155 156 if((mDpy && ctx->deviceOrientation) && 157 ctx->listStats[mDpy].isDisplayAnimating) { 158 fbZorder = 0; 159 } 160 161 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT; 162 ovutils::eIsFg isFg = ovutils::IS_FG_OFF; 163 ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder); 164 165 hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf); 166 hwc_rect_t displayFrame = layer->displayFrame; 167 168 // No FB update optimization on (1) Custom FB resolution, 169 // (2) External Mirror mode, (3) External orientation 170 if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode 171 && !ctx->mExtOrientation) { 172 sourceCrop = fbUpdatingRect; 173 displayFrame = fbUpdatingRect; 174 } 175 176 int transform = layer->transform; 177 int rotFlags = ovutils::ROT_FLAGS_NONE; 178 179 ovutils::eTransform orient = 180 static_cast<ovutils::eTransform>(transform); 181 // use ext orientation if any 182 int extOrient = getExtOrientation(ctx); 183 184 // Do not use getNonWormholeRegion() function to calculate the 185 // sourceCrop during animation on external display and 186 // Dont do wormhole calculation when extorientation is set on External 187 // Dont do wormhole calculation when extDownscale is enabled on External 188 if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) { 189 sourceCrop = layer->displayFrame; 190 } else if((!mDpy || 191 (mDpy && !extOrient 192 && !ctx->dpyAttr[mDpy].mDownScaleMode)) 193 && (extOnlyLayerIndex == -1)) { 194 if(!qdutils::MDPVersion::getInstance().is8x26() && 195 !ctx->dpyAttr[mDpy].customFBSize) { 196 getNonWormholeRegion(list, sourceCrop); 197 displayFrame = sourceCrop; 198 } 199 } 200 calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame, 201 transform, orient); 202 //Store the displayFrame, will be used in getDisplayViewFrame 203 ctx->dpyAttr[mDpy].mDstRect = displayFrame; 204 setMdpFlags(layer, mdpFlags, 0, transform); 205 // For External use rotator if there is a rotation value set 206 ret = preRotateExtDisplay(ctx, layer, info, 207 sourceCrop, mdpFlags, rotFlags); 208 if(!ret) { 209 ALOGE("%s: preRotate for external Failed!", __FUNCTION__); 210 return false; 211 } 212 //For the mdp, since either we are pre-rotating or MDP does flips 213 orient = ovutils::OVERLAY_TRANSFORM_0; 214 transform = 0; 215 ovutils::PipeArgs parg(mdpFlags, info, zOrder, isFg, 216 static_cast<ovutils::eRotFlags>(rotFlags), 217 ovutils::DEFAULT_PLANE_ALPHA, 218 (ovutils::eBlending) 219 getBlending(layer->blending)); 220 ret = true; 221 if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame, 222 NULL, mDest) < 0) { 223 ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy); 224 ret = false; 225 } 226 } 227 return ret; 228} 229 230bool FBUpdateNonSplit::draw(hwc_context_t *ctx, private_handle_t *hnd) 231{ 232 if(!mModeOn) { 233 return true; 234 } 235 bool ret = true; 236 overlay::Overlay& ov = *(ctx->mOverlay); 237 ovutils::eDest dest = mDest; 238 int fd = hnd->fd; 239 uint32_t offset = (uint32_t)hnd->offset; 240 if(mRot) { 241 if(!mRot->queueBuffer(fd, offset)) 242 return false; 243 fd = mRot->getDstMemId(); 244 offset = mRot->getDstOffset(); 245 } 246 if (!ov.queueBuffer(fd, offset, dest)) { 247 ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__); 248 ret = false; 249 } 250 return ret; 251} 252 253//================= High res==================================== 254FBUpdateSplit::FBUpdateSplit(hwc_context_t *ctx, const int& dpy): 255 IFBUpdate(ctx, dpy) {} 256 257void FBUpdateSplit::reset() { 258 IFBUpdate::reset(); 259 mDestLeft = ovutils::OV_INVALID; 260 mDestRight = ovutils::OV_INVALID; 261 mRot = NULL; 262} 263 264bool FBUpdateSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list, 265 hwc_rect_t fbUpdatingRect, int fbZorder) { 266 if(!ctx->mMDP.hasOverlay) { 267 ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays", 268 __FUNCTION__); 269 return false; 270 } 271 ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn); 272 mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder); 273 return mModeOn; 274} 275 276// Configure 277bool FBUpdateSplit::configure(hwc_context_t *ctx, 278 hwc_display_contents_1 *list, hwc_rect_t fbUpdatingRect, int fbZorder) { 279 bool ret = false; 280 hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1]; 281 if (LIKELY(ctx->mOverlay)) { 282 /* External only layer present */ 283 int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex; 284 if(extOnlyLayerIndex != -1) { 285 layer = &list->hwLayers[extOnlyLayerIndex]; 286 layer->compositionType = HWC_OVERLAY; 287 } 288 ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight, 289 ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888, 290 mTileEnabled)); 291 292 overlay::Overlay& ov = *(ctx->mOverlay); 293 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT; 294 ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder); 295 ovutils::eTransform orient = 296 static_cast<ovutils::eTransform>(layer->transform); 297 const int hw_w = ctx->dpyAttr[mDpy].xres; 298 const int hw_h = ctx->dpyAttr[mDpy].yres; 299 const int lSplit = getLeftSplit(ctx, mDpy); 300 mDestLeft = ovutils::OV_INVALID; 301 mDestRight = ovutils::OV_INVALID; 302 303 hwc_rect_t sourceCrop = fbUpdatingRect; 304 hwc_rect_t displayFrame = fbUpdatingRect; 305 306 ret = true; 307 Overlay::PipeSpecs pipeSpecs; 308 pipeSpecs.formatClass = Overlay::FORMAT_RGB; 309 pipeSpecs.needsScaling = qhwc::needsScaling(layer); 310 pipeSpecs.dpy = mDpy; 311 pipeSpecs.fb = true; 312 313 /* Configure left pipe */ 314 if(displayFrame.left < lSplit) { 315 pipeSpecs.mixer = Overlay::MIXER_LEFT; 316 ovutils::eDest destL = ov.getPipe(pipeSpecs); 317 if(destL == ovutils::OV_INVALID) { //None available 318 ALOGE("%s: No pipes available to configure fb for dpy %d's left" 319 " mixer", __FUNCTION__, mDpy); 320 return false; 321 } 322 323 mDestLeft = destL; 324 325 //XXX: FB layer plane alpha is currently sent as zero from 326 //surfaceflinger 327 ovutils::PipeArgs pargL(mdpFlags, 328 info, 329 zOrder, 330 ovutils::IS_FG_OFF, 331 ovutils::ROT_FLAGS_NONE, 332 ovutils::DEFAULT_PLANE_ALPHA, 333 (ovutils::eBlending) 334 getBlending(layer->blending)); 335 hwc_rect_t cropL = sourceCrop; 336 hwc_rect_t dstL = displayFrame; 337 hwc_rect_t scissorL = {0, 0, lSplit, hw_h }; 338 qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0); 339 340 if (configMdp(ctx->mOverlay, pargL, orient, cropL, 341 dstL, NULL, destL)< 0) { 342 ALOGE("%s: configMdp fails for left FB", __FUNCTION__); 343 ret = false; 344 } 345 } 346 347 /* Configure right pipe */ 348 if(displayFrame.right > lSplit) { 349 pipeSpecs.mixer = Overlay::MIXER_RIGHT; 350 ovutils::eDest destR = ov.getPipe(pipeSpecs); 351 if(destR == ovutils::OV_INVALID) { //None available 352 ALOGE("%s: No pipes available to configure fb for dpy %d's" 353 " right mixer", __FUNCTION__, mDpy); 354 return false; 355 } 356 357 mDestRight = destR; 358 ovutils::eMdpFlags mdpFlagsR = mdpFlags; 359 ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER); 360 361 //XXX: FB layer plane alpha is currently sent as zero from 362 //surfaceflinger 363 ovutils::PipeArgs pargR(mdpFlagsR, 364 info, 365 zOrder, 366 ovutils::IS_FG_OFF, 367 ovutils::ROT_FLAGS_NONE, 368 ovutils::DEFAULT_PLANE_ALPHA, 369 (ovutils::eBlending) 370 getBlending(layer->blending)); 371 372 hwc_rect_t cropR = sourceCrop; 373 hwc_rect_t dstR = displayFrame; 374 hwc_rect_t scissorR = {lSplit, 0, hw_w, hw_h }; 375 qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0); 376 377 dstR.left -= lSplit; 378 dstR.right -= lSplit; 379 380 if (configMdp(ctx->mOverlay, pargR, orient, cropR, 381 dstR, NULL, destR) < 0) { 382 ALOGE("%s: configMdp fails for right FB", __FUNCTION__); 383 ret = false; 384 } 385 } 386 } 387 return ret; 388} 389 390bool FBUpdateSplit::draw(hwc_context_t *ctx, private_handle_t *hnd) 391{ 392 if(!mModeOn) { 393 return true; 394 } 395 bool ret = true; 396 overlay::Overlay& ov = *(ctx->mOverlay); 397 if(mDestLeft != ovutils::OV_INVALID) { 398 if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestLeft)) { 399 ALOGE("%s: queue failed for left of dpy = %d", 400 __FUNCTION__, mDpy); 401 ret = false; 402 } 403 } 404 if(mDestRight != ovutils::OV_INVALID) { 405 if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestRight)) { 406 ALOGE("%s: queue failed for right of dpy = %d", 407 __FUNCTION__, mDpy); 408 ret = false; 409 } 410 } 411 return ret; 412} 413 414//=================FBSrcSplit==================================== 415FBSrcSplit::FBSrcSplit(hwc_context_t *ctx, const int& dpy): 416 FBUpdateSplit(ctx, dpy) {} 417 418bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list, 419 hwc_rect_t fbUpdatingRect, int fbZorder) { 420 hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1]; 421 int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex; 422 // ext only layer present.. 423 if(extOnlyLayerIndex != -1) { 424 layer = &list->hwLayers[extOnlyLayerIndex]; 425 layer->compositionType = HWC_OVERLAY; 426 } 427 428 overlay::Overlay& ov = *(ctx->mOverlay); 429 430 ovutils::Whf info(mAlignedFBWidth, 431 mAlignedFBHeight, 432 ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888, 433 mTileEnabled)); 434 435 ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT; 436 ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder); 437 438 ovutils::PipeArgs parg(mdpFlags, 439 info, 440 zOrder, 441 ovutils::IS_FG_OFF, 442 ovutils::ROT_FLAGS_NONE, 443 ovutils::DEFAULT_PLANE_ALPHA, 444 (ovutils::eBlending) 445 getBlending(layer->blending)); 446 447 int transform = layer->transform; 448 ovutils::eTransform orient = 449 static_cast<ovutils::eTransform>(transform); 450 451 hwc_rect_t cropL = fbUpdatingRect; 452 hwc_rect_t cropR = fbUpdatingRect; 453 454 //Request left pipe (or 1 by default) 455 Overlay::PipeSpecs pipeSpecs; 456 pipeSpecs.formatClass = Overlay::FORMAT_RGB; 457 pipeSpecs.needsScaling = qhwc::needsScaling(layer); 458 pipeSpecs.dpy = mDpy; 459 pipeSpecs.mixer = Overlay::MIXER_DEFAULT; 460 pipeSpecs.fb = true; 461 ovutils::eDest destL = ov.getPipe(pipeSpecs); 462 if(destL == ovutils::OV_INVALID) { 463 ALOGE("%s: No pipes available to configure fb for dpy %d's left" 464 " mixer", __FUNCTION__, mDpy); 465 return false; 466 } 467 468 ovutils::eDest destR = ovutils::OV_INVALID; 469 470 /* Use 2 pipes IF 471 a) FB's width is > 2048 or 472 b) On primary, driver has indicated with caps to split always. This is 473 based on an empirically derived value of panel height. 474 */ 475 476 bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and 477 qdutils::MDPVersion::getInstance().isSrcSplitAlways(); 478 int lSplit = getLeftSplit(ctx, mDpy); 479 480 if(((fbUpdatingRect.right - fbUpdatingRect.left) > 481 qdutils::MAX_DISPLAY_DIM) or 482 ((fbUpdatingRect.right - fbUpdatingRect.left) > lSplit and 483 primarySplitAlways)) { 484 destR = ov.getPipe(pipeSpecs); 485 if(destR == ovutils::OV_INVALID) { 486 ALOGE("%s: No pipes available to configure fb for dpy %d's right" 487 " mixer", __FUNCTION__, mDpy); 488 return false; 489 } 490 491 if(ctx->mOverlay->comparePipePriority(destL, destR) == -1) { 492 qhwc::swap(destL, destR); 493 } 494 495 //Split crop equally when using 2 pipes 496 cropL.right = (fbUpdatingRect.right + fbUpdatingRect.left) / 2; 497 cropR.left = cropL.right; 498 } 499 500 mDestLeft = destL; 501 mDestRight = destR; 502 503 if(destL != OV_INVALID) { 504 if(configMdp(ctx->mOverlay, parg, orient, 505 cropL, cropL, NULL /*metadata*/, destL) < 0) { 506 ALOGE("%s: commit failed for left mixer config", __FUNCTION__); 507 return false; 508 } 509 } 510 511 //configure right pipe 512 if(destR != OV_INVALID) { 513 if(configMdp(ctx->mOverlay, parg, orient, 514 cropR, cropR, NULL /*metadata*/, destR) < 0) { 515 ALOGE("%s: commit failed for right mixer config", __FUNCTION__); 516 return false; 517 } 518 } 519 520 return true; 521} 522 523//--------------------------------------------------------------------- 524}; //namespace qhwc 525