1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. 4 * Not a Contribution, Apache license notifications and license are retained 5 * for attribution purposes only. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 #include "overlayUtils.h" 21 #include "overlayRotator.h" 22 23 #define DEBUG_MDSS_ROT 0 24 25 #ifdef VENUS_COLOR_FORMAT 26 #include <media/msm_media_info.h> 27 #else 28 #define VENUS_BUFFER_SIZE(args...) 0 29 #endif 30 31 #ifndef MDSS_MDP_ROT_ONLY 32 #define MDSS_MDP_ROT_ONLY 0x80 33 #endif 34 35 #define SIZE_1M 0x00100000 36 #define MDSS_ROT_MASK (MDP_ROT_90 | MDP_FLIP_UD | MDP_FLIP_LR) 37 38 namespace ovutils = overlay::utils; 39 40 namespace overlay { 41 MdssRot::MdssRot() { 42 reset(); 43 init(); 44 } 45 46 MdssRot::~MdssRot() { close(); } 47 48 bool MdssRot::enabled() const { return mEnabled; } 49 50 void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; } 51 52 int MdssRot::getDstMemId() const { 53 return mRotData.dst_data.memory_id; 54 } 55 56 uint32_t MdssRot::getDstOffset() const { 57 return mRotData.dst_data.offset; 58 } 59 60 uint32_t MdssRot::getDstFormat() const { 61 //For mdss src and dst formats are same 62 return mRotInfo.src.format; 63 } 64 65 uint32_t MdssRot::getSessId() const { return mRotInfo.id; } 66 67 bool MdssRot::init() { 68 if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) { 69 ALOGE("MdssRot failed to init fb0"); 70 return false; 71 } 72 return true; 73 } 74 75 void MdssRot::setSource(const overlay::utils::Whf& awhf) { 76 utils::Whf whf(awhf); 77 78 mRotInfo.src.format = whf.format; 79 mRotInfo.src.width = whf.w; 80 mRotInfo.src.height = whf.h; 81 } 82 83 void MdssRot::setCrop(const utils::Dim& crop) { 84 85 mRotInfo.src_rect.x = crop.x; 86 mRotInfo.src_rect.y = crop.y; 87 mRotInfo.src_rect.w = crop.w; 88 mRotInfo.src_rect.h = crop.h; 89 90 mRotInfo.dst_rect.x = 0; 91 mRotInfo.dst_rect.y = 0; 92 mRotInfo.dst_rect.w = crop.w; 93 mRotInfo.dst_rect.h = crop.h; 94 } 95 96 void MdssRot::setDownscale(int ds) {} 97 98 void MdssRot::setFlags(const utils::eMdpFlags& flags) { 99 mRotInfo.flags = flags; 100 } 101 102 void MdssRot::setTransform(const utils::eTransform& rot) 103 { 104 // reset rotation flags to avoid stale orientation values 105 mRotInfo.flags &= ~MDSS_ROT_MASK; 106 int flags = utils::getMdpOrient(rot); 107 if (flags != -1) 108 setRotations(flags); 109 mOrientation = static_cast<utils::eTransform>(flags); 110 ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags); 111 } 112 113 void MdssRot::doTransform() { 114 mRotInfo.flags |= mOrientation; 115 if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) 116 utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h); 117 } 118 119 bool MdssRot::commit() { 120 doTransform(); 121 mRotInfo.flags |= MDSS_MDP_ROT_ONLY; 122 mEnabled = true; 123 if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) { 124 ALOGE("MdssRot commit failed!"); 125 dump(); 126 return (mEnabled = false); 127 } 128 mRotData.id = mRotInfo.id; 129 return true; 130 } 131 132 bool MdssRot::queueBuffer(int fd, uint32_t offset) { 133 if(enabled()) { 134 mRotData.data.memory_id = fd; 135 mRotData.data.offset = offset; 136 137 remap(RotMem::Mem::ROT_NUM_BUFS); 138 OVASSERT(mMem.curr().m.numBufs(), "queueBuffer numbufs is 0"); 139 140 mRotData.dst_data.offset = 141 mMem.curr().mRotOffset[mMem.curr().mCurrOffset]; 142 mMem.curr().mCurrOffset = 143 (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs(); 144 145 if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) { 146 ALOGE("MdssRot play failed!"); 147 dump(); 148 return false; 149 } 150 151 // if the prev mem is valid, we need to close 152 if(mMem.prev().valid()) { 153 // FIXME if no wait for vsync the above 154 // play will return immediatly and might cause 155 // tearing when prev.close is called. 156 if(!mMem.prev().close()) { 157 ALOGE("%s error in closing prev rot mem", __FUNCTION__); 158 return false; 159 } 160 } 161 } 162 return true; 163 } 164 165 bool MdssRot::open_i(uint32_t numbufs, uint32_t bufsz) 166 { 167 OvMem mem; 168 OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i"); 169 bool isSecure = mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION; 170 171 if(!mem.open(numbufs, bufsz, isSecure)){ 172 ALOGE("%s: Failed to open", __func__); 173 mem.close(); 174 return false; 175 } 176 177 OVASSERT(MAP_FAILED != mem.addr(), "MAP failed"); 178 OVASSERT(mem.getFD() != -1, "getFd is -1"); 179 180 mRotData.dst_data.memory_id = mem.getFD(); 181 mRotData.dst_data.offset = 0; 182 mMem.curr().m = mem; 183 return true; 184 } 185 186 bool MdssRot::remap(uint32_t numbufs) { 187 // Calculate the size based on rotator's dst format, w and h. 188 uint32_t opBufSize = calcOutputBufSize(); 189 // If current size changed, remap 190 if(opBufSize == mMem.curr().size()) { 191 ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize); 192 return true; 193 } 194 195 ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__); 196 OVASSERT(!mMem.prev().valid(), "Prev should not be valid"); 197 198 // ++mMem will make curr to be prev, and prev will be curr 199 ++mMem; 200 if(!open_i(numbufs, opBufSize)) { 201 ALOGE("%s Error could not open", __FUNCTION__); 202 return false; 203 } 204 for (uint32_t i = 0; i < numbufs; ++i) { 205 mMem.curr().mRotOffset[i] = i * opBufSize; 206 } 207 return true; 208 } 209 210 bool MdssRot::close() { 211 bool success = true; 212 if(mFd.valid() && (getSessId() != (uint32_t) MSMFB_NEW_REQUEST)) { 213 if(!mdp_wrapper::unsetOverlay(mFd.getFD(), getSessId())) { 214 ALOGE("MdssRot::close unsetOverlay failed, fd=%d sessId=%d", 215 mFd.getFD(), getSessId()); 216 success = false; 217 } 218 } 219 220 if (!mFd.close()) { 221 ALOGE("Mdss Rot error closing fd"); 222 success = false; 223 } 224 if (!mMem.close()) { 225 ALOGE("Mdss Rot error closing mem"); 226 success = false; 227 } 228 reset(); 229 return success; 230 } 231 232 void MdssRot::reset() { 233 ovutils::memset0(mRotInfo); 234 ovutils::memset0(mRotData); 235 mRotData.data.memory_id = -1; 236 mRotInfo.id = MSMFB_NEW_REQUEST; 237 ovutils::memset0(mMem.curr().mRotOffset); 238 ovutils::memset0(mMem.prev().mRotOffset); 239 mMem.curr().mCurrOffset = 0; 240 mMem.prev().mCurrOffset = 0; 241 mOrientation = utils::OVERLAY_TRANSFORM_0; 242 } 243 244 void MdssRot::dump() const { 245 ALOGE("== Dump MdssRot start =="); 246 mFd.dump(); 247 mMem.curr().m.dump(); 248 mdp_wrapper::dump("mRotInfo", mRotInfo); 249 mdp_wrapper::dump("mRotData", mRotData); 250 ALOGE("== Dump MdssRot end =="); 251 } 252 253 uint32_t MdssRot::calcOutputBufSize() { 254 uint32_t opBufSize = 0; 255 ovutils::Whf destWhf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h, 256 mRotInfo.src.format); //mdss src and dst formats are same. 257 258 if (mRotInfo.flags & ovutils::OV_MDSS_MDP_BWC_EN) { 259 opBufSize = calcCompressedBufSize(destWhf); 260 } else { 261 opBufSize = Rotator::calcOutputBufSize(destWhf); 262 } 263 264 if (mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION) 265 opBufSize = utils::align(opBufSize, SIZE_1M); 266 267 return opBufSize; 268 } 269 270 void MdssRot::getDump(char *buf, size_t len) const { 271 ovutils::getDump(buf, len, "MdssRotCtrl", mRotInfo); 272 ovutils::getDump(buf, len, "MdssRotData", mRotData); 273 } 274 275 // Calculate the compressed o/p buffer size for BWC 276 uint32_t MdssRot::calcCompressedBufSize(const ovutils::Whf& destWhf) { 277 uint32_t bufSize = 0; 278 int aWidth = ovutils::align(destWhf.w, 64); 279 int aHeight = ovutils::align(destWhf.h, 4); 280 int rau_cnt = aWidth/64; 281 int stride0 = (64 * 4 * rau_cnt) + rau_cnt/8; 282 int stride1 = ((64 * 2 * rau_cnt) + rau_cnt/8) * 2; 283 int stride0_off = (aHeight/4); 284 int stride1_off = (aHeight/2); 285 286 //New o/p size for BWC 287 bufSize = (stride0 * stride0_off + stride1 * stride1_off) + 288 (rau_cnt * 2 * (stride0_off + stride1_off)); 289 ALOGD_IF(DEBUG_MDSS_ROT, "%s: width = %d, height = %d raucount = %d" 290 "opBufSize = %d ", __FUNCTION__, aWidth, aHeight, rau_cnt, bufSize); 291 return bufSize; 292 } 293 294 } // namespace overlay 295