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 #ifdef VENUS_COLOR_FORMAT 24 #include <media/msm_media_info.h> 25 #else 26 #define VENUS_BUFFER_SIZE(args...) 0 27 #endif 28 29 #ifndef MDSS_MDP_ROT_ONLY 30 #define MDSS_MDP_ROT_ONLY 0x80 31 #endif 32 33 #define SIZE_1M 0x00100000 34 #define MDSS_ROT_MASK (MDP_ROT_90 | MDP_FLIP_UD | MDP_FLIP_LR) 35 36 namespace ovutils = overlay::utils; 37 38 namespace overlay { 39 MdssRot::MdssRot() { 40 reset(); 41 init(); 42 } 43 44 MdssRot::~MdssRot() { close(); } 45 46 bool MdssRot::enabled() const { return mEnabled; } 47 48 void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; } 49 50 int MdssRot::getDstMemId() const { 51 return mRotData.dst_data.memory_id; 52 } 53 54 uint32_t MdssRot::getDstOffset() const { 55 return mRotData.dst_data.offset; 56 } 57 58 uint32_t MdssRot::getDstFormat() const { 59 //For mdss src and dst formats are same 60 return mRotInfo.src.format; 61 } 62 63 uint32_t MdssRot::getSessId() const { return mRotInfo.id; } 64 65 bool MdssRot::init() { 66 if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) { 67 ALOGE("MdssRot failed to init fb0"); 68 return false; 69 } 70 return true; 71 } 72 73 void MdssRot::setSource(const overlay::utils::Whf& awhf) { 74 utils::Whf whf(awhf); 75 76 mRotInfo.src.format = whf.format; 77 78 mRotInfo.src.width = whf.w; 79 mRotInfo.src.height = whf.h; 80 81 mRotInfo.src_rect.w = whf.w; 82 mRotInfo.src_rect.h = whf.h; 83 84 mRotInfo.dst_rect.w = whf.w; 85 mRotInfo.dst_rect.h = whf.h; 86 } 87 88 void MdssRot::setSource(const overlay::utils::Whf& awhf, 89 const overlay::utils::Whf& owhf) { 90 setSource(awhf); 91 } 92 93 void MdssRot::setDownscale(int ds) {} 94 95 void MdssRot::setFlags(const utils::eMdpFlags& flags) { 96 mRotInfo.flags |= flags; 97 } 98 99 void MdssRot::setTransform(const utils::eTransform& rot) 100 { 101 // reset rotation flags to avoid stale orientation values 102 mRotInfo.flags &= ~MDSS_ROT_MASK; 103 int flags = utils::getMdpOrient(rot); 104 if (flags != -1) 105 setRotations(flags); 106 //getMdpOrient will switch the flips if the source is 90 rotated. 107 //Clients in Android dont factor in 90 rotation while deciding the flip. 108 mOrientation = static_cast<utils::eTransform>(flags); 109 ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags); 110 } 111 112 void MdssRot::doTransform() { 113 if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) 114 utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h); 115 } 116 117 bool MdssRot::commit() { 118 doTransform(); 119 mRotInfo.flags |= MDSS_MDP_ROT_ONLY; 120 mEnabled = true; 121 if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) { 122 ALOGE("MdssRot commit failed!"); 123 dump(); 124 return (mEnabled = false); 125 } 126 mRotData.id = mRotInfo.id; 127 return true; 128 } 129 130 bool MdssRot::queueBuffer(int fd, uint32_t offset) { 131 if(enabled()) { 132 mRotData.data.memory_id = fd; 133 mRotData.data.offset = offset; 134 135 remap(RotMem::Mem::ROT_NUM_BUFS); 136 OVASSERT(mMem.curr().m.numBufs(), "queueBuffer numbufs is 0"); 137 138 mRotData.dst_data.offset = 139 mMem.curr().mRotOffset[mMem.curr().mCurrOffset]; 140 mMem.curr().mCurrOffset = 141 (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs(); 142 143 if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) { 144 ALOGE("MdssRot play failed!"); 145 dump(); 146 return false; 147 } 148 149 // if the prev mem is valid, we need to close 150 if(mMem.prev().valid()) { 151 // FIXME if no wait for vsync the above 152 // play will return immediatly and might cause 153 // tearing when prev.close is called. 154 if(!mMem.prev().close()) { 155 ALOGE("%s error in closing prev rot mem", __FUNCTION__); 156 return false; 157 } 158 } 159 } 160 return true; 161 } 162 163 bool MdssRot::open_i(uint32_t numbufs, uint32_t bufsz) 164 { 165 OvMem mem; 166 OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i"); 167 bool isSecure = mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION; 168 169 if(!mem.open(numbufs, bufsz, isSecure)){ 170 ALOGE("%s: Failed to open", __func__); 171 mem.close(); 172 return false; 173 } 174 175 OVASSERT(MAP_FAILED != mem.addr(), "MAP failed"); 176 OVASSERT(mem.getFD() != -1, "getFd is -1"); 177 178 mRotData.dst_data.memory_id = mem.getFD(); 179 mRotData.dst_data.offset = 0; 180 mMem.curr().m = mem; 181 return true; 182 } 183 184 bool MdssRot::remap(uint32_t numbufs) { 185 // Calculate the size based on rotator's dst format, w and h. 186 uint32_t opBufSize = calcOutputBufSize(); 187 // If current size changed, remap 188 if(opBufSize == mMem.curr().size()) { 189 ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize); 190 return true; 191 } 192 193 ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__); 194 OVASSERT(!mMem.prev().valid(), "Prev should not be valid"); 195 196 // ++mMem will make curr to be prev, and prev will be curr 197 ++mMem; 198 if(!open_i(numbufs, opBufSize)) { 199 ALOGE("%s Error could not open", __FUNCTION__); 200 return false; 201 } 202 for (uint32_t i = 0; i < numbufs; ++i) { 203 mMem.curr().mRotOffset[i] = i * opBufSize; 204 } 205 return true; 206 } 207 208 bool MdssRot::close() { 209 bool success = true; 210 if(mFd.valid() && (getSessId() != (uint32_t) MSMFB_NEW_REQUEST)) { 211 if(!mdp_wrapper::unsetOverlay(mFd.getFD(), getSessId())) { 212 ALOGE("MdssRot::close unsetOverlay failed, fd=%d sessId=%d", 213 mFd.getFD(), getSessId()); 214 success = false; 215 } 216 } 217 218 if (!mFd.close()) { 219 ALOGE("Mdss Rot error closing fd"); 220 success = false; 221 } 222 if (!mMem.close()) { 223 ALOGE("Mdss Rot error closing mem"); 224 success = false; 225 } 226 reset(); 227 return success; 228 } 229 230 void MdssRot::reset() { 231 ovutils::memset0(mRotInfo); 232 ovutils::memset0(mRotData); 233 mRotData.data.memory_id = -1; 234 mRotInfo.id = MSMFB_NEW_REQUEST; 235 ovutils::memset0(mMem.curr().mRotOffset); 236 ovutils::memset0(mMem.prev().mRotOffset); 237 mMem.curr().mCurrOffset = 0; 238 mMem.prev().mCurrOffset = 0; 239 mOrientation = utils::OVERLAY_TRANSFORM_0; 240 } 241 242 void MdssRot::dump() const { 243 ALOGE("== Dump MdssRot start =="); 244 mFd.dump(); 245 mMem.curr().m.dump(); 246 mdp_wrapper::dump("mRotInfo", mRotInfo); 247 mdp_wrapper::dump("mRotData", mRotData); 248 ALOGE("== Dump MdssRot end =="); 249 } 250 251 uint32_t MdssRot::calcOutputBufSize() { 252 uint32_t opBufSize = 0; 253 ovutils::Whf destWhf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h, 254 mRotInfo.src.format); //mdss src and dst formats are same. 255 256 opBufSize = Rotator::calcOutputBufSize(destWhf); 257 258 if (mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION) 259 opBufSize = utils::align(opBufSize, SIZE_1M); 260 261 return opBufSize; 262 } 263 264 void MdssRot::getDump(char *buf, size_t len) const { 265 ovutils::getDump(buf, len, "MdssRotCtrl(mdp_overlay)", mRotInfo); 266 ovutils::getDump(buf, len, "MdssRotData(msmfb_overlay_data)", mRotData); 267 } 268 269 } // namespace overlay 270