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