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