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