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