1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * Copyright (C) 2012-2013, 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 <gralloc_priv.h> 23#include <overlay.h> 24#include "hwc_fbupdate.h" 25#include "mdp_version.h" 26 27using namespace qdutils; 28using namespace overlay; 29 30namespace qhwc { 31 32namespace ovutils = overlay::utils; 33 34IFBUpdate* IFBUpdate::getObject(const int& width, const int& rightSplit, 35 const int& dpy) { 36 if(width > MAX_DISPLAY_DIM || rightSplit) { 37 return new FBUpdateHighRes(dpy); 38 } 39 return new FBUpdateLowRes(dpy); 40} 41 42inline void IFBUpdate::reset() { 43 mModeOn = false; 44} 45 46//================= Low res==================================== 47FBUpdateLowRes::FBUpdateLowRes(const int& dpy): IFBUpdate(dpy) {} 48 49inline void FBUpdateLowRes::reset() { 50 IFBUpdate::reset(); 51 mDest = ovutils::OV_INVALID; 52} 53 54bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list, 55 int fbZorder) { 56 if(!ctx->mMDP.hasOverlay) { 57 ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays", 58 __FUNCTION__); 59 return false; 60 } 61 mModeOn = configure(ctx, list, fbZorder); 62 return mModeOn; 63} 64 65// Configure 66bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_display_contents_1 *list, 67 int fbZorder) { 68 bool ret = false; 69 hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1]; 70 if (LIKELY(ctx->mOverlay)) { 71 overlay::Overlay& ov = *(ctx->mOverlay); 72 hwc_rect_t displayFrame = layer->displayFrame; 73 int alignedWidth = 0; 74 int alignedHeight = 0; 75 76 getBufferSizeAndDimensions(displayFrame.right - displayFrame.left, 77 displayFrame.bottom - displayFrame.top, 78 HAL_PIXEL_FORMAT_RGBA_8888, 79 alignedWidth, 80 alignedHeight); 81 82 ovutils::Whf info(alignedWidth, 83 alignedHeight, 84 ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888)); 85 86 //Request a pipe 87 ovutils::eMdpPipeType type = ovutils::OV_MDP_PIPE_ANY; 88 if(qdutils::MDPVersion::getInstance().is8x26() && mDpy) { 89 //For 8x26 external always use DMA pipe 90 type = ovutils::OV_MDP_PIPE_DMA; 91 } 92 ovutils::eDest dest = ov.nextPipe(type, mDpy, Overlay::MIXER_DEFAULT); 93 if(dest == ovutils::OV_INVALID) { //None available 94 ALOGE("%s: No pipes available to configure framebuffer", 95 __FUNCTION__); 96 return false; 97 } 98 99 mDest = dest; 100 101 ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT; 102 103 ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder); 104 105 //XXX: FB layer plane alpha is currently sent as zero from 106 //surfaceflinger 107 ovutils::PipeArgs parg(mdpFlags, 108 info, 109 zOrder, 110 ovutils::IS_FG_OFF, 111 ovutils::ROT_FLAGS_NONE, 112 ovutils::DEFAULT_PLANE_ALPHA, 113 (ovutils::eBlending) getBlending(layer->blending)); 114 ov.setSource(parg, dest); 115 116 hwc_rect_t sourceCrop; 117 getNonWormholeRegion(list, sourceCrop); 118 // x,y,w,h 119 ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, 120 sourceCrop.right - sourceCrop.left, 121 sourceCrop.bottom - sourceCrop.top); 122 ov.setCrop(dcrop, dest); 123 124 int transform = layer->transform; 125 ovutils::eTransform orient = 126 static_cast<ovutils::eTransform>(transform); 127 ov.setTransform(orient, dest); 128 129 if(!qdutils::MDPVersion::getInstance().is8x26()) { 130 getNonWormholeRegion(list, sourceCrop); 131 } 132 133 displayFrame = sourceCrop; 134 ovutils::Dim dpos(displayFrame.left, 135 displayFrame.top, 136 displayFrame.right - displayFrame.left, 137 displayFrame.bottom - displayFrame.top); 138 139 if(mDpy && !qdutils::MDPVersion::getInstance().is8x26()) 140 // Calculate the actionsafe dimensions for External(dpy = 1 or 2) 141 getActionSafePosition(ctx, mDpy, dpos.x, dpos.y, dpos.w, dpos.h); 142 ov.setPosition(dpos, dest); 143 144 ret = true; 145 if (!ov.commit(dest)) { 146 ALOGE("%s: commit fails", __FUNCTION__); 147 ret = false; 148 } 149 } 150 return ret; 151} 152 153bool FBUpdateLowRes::draw(hwc_context_t *ctx, private_handle_t *hnd) 154{ 155 if(!mModeOn) { 156 return true; 157 } 158 bool ret = true; 159 overlay::Overlay& ov = *(ctx->mOverlay); 160 ovutils::eDest dest = mDest; 161 if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) { 162 ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__); 163 ret = false; 164 } 165 return ret; 166} 167 168//================= High res==================================== 169FBUpdateHighRes::FBUpdateHighRes(const int& dpy): IFBUpdate(dpy) {} 170 171inline void FBUpdateHighRes::reset() { 172 IFBUpdate::reset(); 173 mDestLeft = ovutils::OV_INVALID; 174 mDestRight = ovutils::OV_INVALID; 175} 176 177bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list, 178 int fbZorder) { 179 if(!ctx->mMDP.hasOverlay) { 180 ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays", 181 __FUNCTION__); 182 return false; 183 } 184 ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn); 185 mModeOn = configure(ctx, list, fbZorder); 186 return mModeOn; 187} 188 189// Configure 190bool FBUpdateHighRes::configure(hwc_context_t *ctx, 191 hwc_display_contents_1 *list, int fbZorder) { 192 bool ret = false; 193 hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1]; 194 if (LIKELY(ctx->mOverlay)) { 195 overlay::Overlay& ov = *(ctx->mOverlay); 196 hwc_rect_t displayFrame = layer->displayFrame; 197 int alignedWidth = 0; 198 int alignedHeight = 0; 199 200 getBufferSizeAndDimensions(displayFrame.right - displayFrame.left, 201 displayFrame.bottom - displayFrame.top, 202 HAL_PIXEL_FORMAT_RGBA_8888, 203 alignedWidth, 204 alignedHeight); 205 206 ovutils::Whf info(alignedWidth, 207 alignedHeight, 208 ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888)); 209 210 //Request left pipe 211 ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy, 212 Overlay::MIXER_LEFT); 213 if(destL == ovutils::OV_INVALID) { //None available 214 ALOGE("%s: No pipes available to configure framebuffer", 215 __FUNCTION__); 216 return false; 217 } 218 //Request right pipe 219 ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy, 220 Overlay::MIXER_RIGHT); 221 if(destR == ovutils::OV_INVALID) { //None available 222 ALOGE("%s: No pipes available to configure framebuffer", 223 __FUNCTION__); 224 return false; 225 } 226 227 mDestLeft = destL; 228 mDestRight = destR; 229 230 ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_BLEND_FG_PREMULT; 231 232 ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder); 233 234 //XXX: FB layer plane alpha is currently sent as zero from 235 //surfaceflinger 236 ovutils::PipeArgs pargL(mdpFlagsL, 237 info, 238 zOrder, 239 ovutils::IS_FG_OFF, 240 ovutils::ROT_FLAGS_NONE, 241 ovutils::DEFAULT_PLANE_ALPHA, 242 (ovutils::eBlending) getBlending(layer->blending)); 243 ov.setSource(pargL, destL); 244 245 ovutils::eMdpFlags mdpFlagsR = mdpFlagsL; 246 ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER); 247 ovutils::PipeArgs pargR(mdpFlagsR, 248 info, 249 zOrder, 250 ovutils::IS_FG_OFF, 251 ovutils::ROT_FLAGS_NONE, 252 ovutils::DEFAULT_PLANE_ALPHA, 253 (ovutils::eBlending) getBlending(layer->blending)); 254 ov.setSource(pargR, destR); 255 256 hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf); 257 258 const float xres = ctx->dpyAttr[mDpy].xres; 259 const int lSplit = getLeftSplit(ctx, mDpy); 260 const float lSplitRatio = lSplit / xres; 261 const float lCropWidth = 262 (sourceCrop.right - sourceCrop.left) * lSplitRatio; 263 264 ovutils::Dim dcropL( 265 sourceCrop.left, 266 sourceCrop.top, 267 lCropWidth, 268 sourceCrop.bottom - sourceCrop.top); 269 270 ovutils::Dim dcropR( 271 sourceCrop.left + lCropWidth, 272 sourceCrop.top, 273 (sourceCrop.right - sourceCrop.left) - lCropWidth, 274 sourceCrop.bottom - sourceCrop.top); 275 276 ov.setCrop(dcropL, destL); 277 ov.setCrop(dcropR, destR); 278 279 int transform = layer->transform; 280 ovutils::eTransform orient = 281 static_cast<ovutils::eTransform>(transform); 282 ov.setTransform(orient, destL); 283 ov.setTransform(orient, destR); 284 285 const int lWidth = (lSplit - displayFrame.left); 286 const int rWidth = (displayFrame.right - lSplit); 287 const int height = displayFrame.bottom - displayFrame.top; 288 289 ovutils::Dim dposL(displayFrame.left, 290 displayFrame.top, 291 lWidth, 292 height); 293 ov.setPosition(dposL, destL); 294 295 ovutils::Dim dposR(0, 296 displayFrame.top, 297 rWidth, 298 height); 299 ov.setPosition(dposR, destR); 300 301 ret = true; 302 if (!ov.commit(destL)) { 303 ALOGE("%s: commit fails for left", __FUNCTION__); 304 ret = false; 305 } 306 if (!ov.commit(destR)) { 307 ALOGE("%s: commit fails for right", __FUNCTION__); 308 ret = false; 309 } 310 } 311 return ret; 312} 313 314bool FBUpdateHighRes::draw(hwc_context_t *ctx, private_handle_t *hnd) 315{ 316 if(!mModeOn) { 317 return true; 318 } 319 bool ret = true; 320 overlay::Overlay& ov = *(ctx->mOverlay); 321 ovutils::eDest destL = mDestLeft; 322 ovutils::eDest destR = mDestRight; 323 if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) { 324 ALOGE("%s: queue failed for left of dpy = %d", 325 __FUNCTION__, mDpy); 326 ret = false; 327 } 328 if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) { 329 ALOGE("%s: queue failed for right of dpy = %d", 330 __FUNCTION__, mDpy); 331 ret = false; 332 } 333 return ret; 334} 335 336//--------------------------------------------------------------------- 337}; //namespace qhwc 338