hwc_fbupdate.cpp revision d5d41f238fd48170a0755bde427088c92ca0920c
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(isDisplaySplit(ctx, dpy)) { 42 return new FBUpdateSplit(ctx, dpy); 43 } 44 return new FBUpdateNonSplit(ctx, dpy); 45} 46 47IFBUpdate::IFBUpdate(hwc_context_t *ctx, const int& dpy) : mDpy(dpy) { 48 size_t size = 0; 49 getBufferAttributes(ctx->dpyAttr[mDpy].xres, 50 ctx->dpyAttr[mDpy].yres, 51 HAL_PIXEL_FORMAT_RGBA_8888, 52 0, 53 mAlignedFBWidth, 54 mAlignedFBHeight, 55 mTileEnabled, size); 56} 57 58void IFBUpdate::reset() { 59 mModeOn = false; 60 mRot = NULL; 61} 62 63bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx, 64 hwc_display_contents_1 *list, int fbZorder) { 65 hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1]; 66 return prepare(ctx, list, layer->displayFrame, fbZorder) && 67 ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd); 68} 69 70//================= Low res==================================== 71FBUpdateNonSplit::FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy): 72 IFBUpdate(ctx, dpy) {} 73 74void FBUpdateNonSplit::reset() { 75 IFBUpdate::reset(); 76 mDest = ovutils::OV_INVALID; 77} 78 79bool FBUpdateNonSplit::preRotateExtDisplay(hwc_context_t *ctx, 80 hwc_layer_1_t *layer, 81 ovutils::Whf &info, 82 hwc_rect_t& sourceCrop, 83 ovutils::eMdpFlags& mdpFlags, 84 int& rotFlags) 85{ 86 int extOrient = getExtOrientation(ctx); 87 ovutils::eTransform orient = static_cast<ovutils::eTransform >(extOrient); 88 if(mDpy && (extOrient & HWC_TRANSFORM_ROT_90)) { 89 mRot = ctx->mRotMgr->getNext(); 90 if(mRot == NULL) return false; 91 // Composed FB content will have black bars, if the viewFrame of the 92 // external is different from {0, 0, fbWidth, fbHeight}, so intersect 93 // viewFrame with sourceCrop to avoid those black bars 94 sourceCrop = getIntersection(sourceCrop, ctx->mViewFrame[mDpy]); 95 //Configure rotator for pre-rotation 96 if(configRotator(mRot, info, sourceCrop, mdpFlags, orient, 0) < 0) { 97 ALOGE("%s: configRotator Failed!", __FUNCTION__); 98 mRot = NULL; 99 return false; 100 } 101 ctx->mLayerRotMap[mDpy]->add(layer, mRot); 102 info.format = (mRot)->getDstFormat(); 103 updateSource(orient, info, sourceCrop); 104 rotFlags |= ovutils::ROT_PREROTATED; 105 } 106 return true; 107} 108 109bool FBUpdateNonSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list, 110 hwc_rect_t fbUpdatingRect, int fbZorder) { 111 if(!ctx->mMDP.hasOverlay) { 112 ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays", 113 __FUNCTION__); 114 return false; 115 } 116 mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder); 117 return mModeOn; 118} 119 120// Configure 121bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list, 122 hwc_rect_t fbUpdatingRect, int fbZorder) { 123 bool ret = false; 124 hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1]; 125 if (LIKELY(ctx->mOverlay)) { 126 int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex; 127 // ext only layer present.. 128 if(extOnlyLayerIndex != -1) { 129 layer = &list->hwLayers[extOnlyLayerIndex]; 130 layer->compositionType = HWC_OVERLAY; 131 } 132 overlay::Overlay& ov = *(ctx->mOverlay); 133 134 ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight, 135 ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888, 136 mTileEnabled)); 137 138 //Request a pipe 139 ovutils::eMdpPipeType type = ovutils::OV_MDP_PIPE_ANY; 140 if(qdutils::MDPVersion::getInstance().is8x26() && mDpy) { 141 //For 8x26 external always use DMA pipe 142 type = ovutils::OV_MDP_PIPE_DMA; 143 } 144 ovutils::eDest dest = ov.nextPipe(type, mDpy, Overlay::MIXER_DEFAULT); 145 if(dest == ovutils::OV_INVALID) { //None available 146 ALOGE("%s: No pipes available to configure fb for dpy %d", 147 __FUNCTION__, mDpy); 148 return false; 149 } 150 mDest = dest; 151 152 if((mDpy && ctx->deviceOrientation) && 153 ctx->listStats[mDpy].isDisplayAnimating) { 154 fbZorder = 0; 155 } 156 157 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT; 158 ovutils::eIsFg isFg = ovutils::IS_FG_OFF; 159 ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder); 160 161 hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf); 162 hwc_rect_t displayFrame = layer->displayFrame; 163 164 // No FB update optimization on (1) Custom FB resolution, 165 // (2) External Mirror mode, (3) External orientation 166 if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode 167 && !ctx->mExtOrientation) { 168 sourceCrop = fbUpdatingRect; 169 displayFrame = fbUpdatingRect; 170 } 171 172 int transform = layer->transform; 173 int rotFlags = ovutils::ROT_FLAGS_NONE; 174 175 ovutils::eTransform orient = 176 static_cast<ovutils::eTransform>(transform); 177 // use ext orientation if any 178 int extOrient = getExtOrientation(ctx); 179 180 // Do not use getNonWormholeRegion() function to calculate the 181 // sourceCrop during animation on external display and 182 // Dont do wormhole calculation when extorientation is set on External 183 // Dont do wormhole calculation when extDownscale is enabled on External 184 if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) { 185 sourceCrop = layer->displayFrame; 186 } else if((!mDpy || 187 (mDpy && !extOrient 188 && !ctx->dpyAttr[mDpy].mDownScaleMode)) 189 && (extOnlyLayerIndex == -1)) { 190 if(!qdutils::MDPVersion::getInstance().is8x26() && 191 !ctx->dpyAttr[mDpy].customFBSize) { 192 getNonWormholeRegion(list, sourceCrop); 193 displayFrame = sourceCrop; 194 } 195 } 196 calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame, 197 transform, orient); 198 //Store the displayFrame, will be used in getDisplayViewFrame 199 ctx->dpyAttr[mDpy].mDstRect = displayFrame; 200 setMdpFlags(layer, mdpFlags, 0, transform); 201 // For External use rotator if there is a rotation value set 202 ret = preRotateExtDisplay(ctx, layer, info, 203 sourceCrop, mdpFlags, rotFlags); 204 if(!ret) { 205 ALOGE("%s: preRotate for external Failed!", __FUNCTION__); 206 ctx->mOverlay->clear(mDpy); 207 ctx->mLayerRotMap[mDpy]->clear(); 208 return false; 209 } 210 //For the mdp, since either we are pre-rotating or MDP does flips 211 orient = ovutils::OVERLAY_TRANSFORM_0; 212 transform = 0; 213 ovutils::PipeArgs parg(mdpFlags, info, zOrder, isFg, 214 static_cast<ovutils::eRotFlags>(rotFlags), 215 ovutils::DEFAULT_PLANE_ALPHA, 216 (ovutils::eBlending) 217 getBlending(layer->blending)); 218 ret = true; 219 if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame, 220 NULL, mDest) < 0) { 221 ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy); 222 ctx->mLayerRotMap[mDpy]->clear(); 223 ret = false; 224 } 225 } 226 return ret; 227} 228 229bool FBUpdateNonSplit::draw(hwc_context_t *ctx, private_handle_t *hnd) 230{ 231 if(!mModeOn) { 232 return true; 233 } 234 bool ret = true; 235 overlay::Overlay& ov = *(ctx->mOverlay); 236 ovutils::eDest dest = mDest; 237 int fd = hnd->fd; 238 uint32_t offset = hnd->offset; 239 if(mRot) { 240 if(!mRot->queueBuffer(fd, offset)) 241 return false; 242 fd = mRot->getDstMemId(); 243 offset = mRot->getDstOffset(); 244 } 245 if (!ov.queueBuffer(fd, offset, dest)) { 246 ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__); 247 ret = false; 248 } 249 return ret; 250} 251 252//================= High res==================================== 253FBUpdateSplit::FBUpdateSplit(hwc_context_t *ctx, const int& dpy): 254 IFBUpdate(ctx, dpy) {} 255 256void FBUpdateSplit::reset() { 257 IFBUpdate::reset(); 258 mDestLeft = ovutils::OV_INVALID; 259 mDestRight = ovutils::OV_INVALID; 260 mRot = NULL; 261} 262 263bool FBUpdateSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list, 264 hwc_rect_t fbUpdatingRect, int fbZorder) { 265 if(!ctx->mMDP.hasOverlay) { 266 ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays", 267 __FUNCTION__); 268 return false; 269 } 270 ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn); 271 mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder); 272 return mModeOn; 273} 274 275// Configure 276bool FBUpdateSplit::configure(hwc_context_t *ctx, 277 hwc_display_contents_1 *list, hwc_rect_t fbUpdatingRect, int fbZorder) { 278 bool ret = false; 279 hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1]; 280 if (LIKELY(ctx->mOverlay)) { 281 int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex; 282 // ext only layer present.. 283 if(extOnlyLayerIndex != -1) { 284 layer = &list->hwLayers[extOnlyLayerIndex]; 285 layer->compositionType = HWC_OVERLAY; 286 } 287 overlay::Overlay& ov = *(ctx->mOverlay); 288 289 ovutils::Whf info(mAlignedFBWidth, 290 mAlignedFBHeight, 291 ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888, 292 mTileEnabled)); 293 //Request left pipe 294 ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy, 295 Overlay::MIXER_LEFT); 296 if(destL == ovutils::OV_INVALID) { //None available 297 ALOGE("%s: No pipes available to configure fb for dpy %d's left" 298 " mixer", __FUNCTION__, mDpy); 299 return false; 300 } 301 //Request right pipe 302 ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy, 303 Overlay::MIXER_RIGHT); 304 if(destR == ovutils::OV_INVALID) { //None available 305 ALOGE("%s: No pipes available to configure fb for dpy %d's right" 306 " mixer", __FUNCTION__, mDpy); 307 return false; 308 } 309 310 mDestLeft = destL; 311 mDestRight = destR; 312 313 ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_BLEND_FG_PREMULT; 314 315 ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder); 316 317 //XXX: FB layer plane alpha is currently sent as zero from 318 //surfaceflinger 319 ovutils::PipeArgs pargL(mdpFlagsL, 320 info, 321 zOrder, 322 ovutils::IS_FG_OFF, 323 ovutils::ROT_FLAGS_NONE, 324 ovutils::DEFAULT_PLANE_ALPHA, 325 (ovutils::eBlending) 326 getBlending(layer->blending)); 327 ov.setSource(pargL, destL); 328 329 ovutils::eMdpFlags mdpFlagsR = mdpFlagsL; 330 ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER); 331 ovutils::PipeArgs pargR(mdpFlagsR, 332 info, 333 zOrder, 334 ovutils::IS_FG_OFF, 335 ovutils::ROT_FLAGS_NONE, 336 ovutils::DEFAULT_PLANE_ALPHA, 337 (ovutils::eBlending) 338 getBlending(layer->blending)); 339 ov.setSource(pargR, destR); 340 341 hwc_rect_t sourceCrop = fbUpdatingRect; 342 hwc_rect_t displayFrame = fbUpdatingRect; 343 344 const float xres = ctx->dpyAttr[mDpy].xres; 345 const int lSplit = getLeftSplit(ctx, mDpy); 346 const float lSplitRatio = lSplit / xres; 347 const float lCropWidth = 348 (sourceCrop.right - sourceCrop.left) * lSplitRatio; 349 350 ovutils::Dim dcropL( 351 sourceCrop.left, 352 sourceCrop.top, 353 lCropWidth, 354 sourceCrop.bottom - sourceCrop.top); 355 356 ovutils::Dim dcropR( 357 sourceCrop.left + lCropWidth, 358 sourceCrop.top, 359 (sourceCrop.right - sourceCrop.left) - lCropWidth, 360 sourceCrop.bottom - sourceCrop.top); 361 362 ov.setCrop(dcropL, destL); 363 ov.setCrop(dcropR, destR); 364 365 int transform = layer->transform; 366 ovutils::eTransform orient = 367 static_cast<ovutils::eTransform>(transform); 368 ov.setTransform(orient, destL); 369 ov.setTransform(orient, destR); 370 371 const int lWidth = (lSplit - displayFrame.left); 372 const int rWidth = (displayFrame.right - lSplit); 373 const int height = displayFrame.bottom - displayFrame.top; 374 375 ovutils::Dim dposL(displayFrame.left, 376 displayFrame.top, 377 lWidth, 378 height); 379 ov.setPosition(dposL, destL); 380 381 ovutils::Dim dposR(0, 382 displayFrame.top, 383 rWidth, 384 height); 385 ov.setPosition(dposR, destR); 386 387 ret = true; 388 if (!ov.commit(destL)) { 389 ALOGE("%s: commit fails for left", __FUNCTION__); 390 ret = false; 391 } 392 if (!ov.commit(destR)) { 393 ALOGE("%s: commit fails for right", __FUNCTION__); 394 ret = false; 395 } 396 if(ret == false) { 397 ctx->mLayerRotMap[mDpy]->clear(); 398 } 399 } 400 return ret; 401} 402 403bool FBUpdateSplit::draw(hwc_context_t *ctx, private_handle_t *hnd) 404{ 405 if(!mModeOn) { 406 return true; 407 } 408 bool ret = true; 409 overlay::Overlay& ov = *(ctx->mOverlay); 410 ovutils::eDest destL = mDestLeft; 411 ovutils::eDest destR = mDestRight; 412 if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) { 413 ALOGE("%s: queue failed for left of dpy = %d", 414 __FUNCTION__, mDpy); 415 ret = false; 416 } 417 if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) { 418 ALOGE("%s: queue failed for right of dpy = %d", 419 __FUNCTION__, mDpy); 420 ret = false; 421 } 422 return ret; 423} 424 425//--------------------------------------------------------------------- 426}; //namespace qhwc 427