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