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::setDownscale(int ds) {} 89 90 void MdssRot::setFlags(const utils::eMdpFlags& flags) { 91 mRotInfo.flags |= flags; 92 } 93 94 void MdssRot::setTransform(const utils::eTransform& rot) 95 { 96 // reset rotation flags to avoid stale orientation values 97 mRotInfo.flags &= ~MDSS_ROT_MASK; 98 int flags = utils::getMdpOrient(rot); 99 if (flags != -1) 100 setRotations(flags); 101 //getMdpOrient will switch the flips if the source is 90 rotated. 102 //Clients in Android dont factor in 90 rotation while deciding the flip. 103 mOrientation = static_cast<utils::eTransform>(flags); 104 ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags); 105 } 106 107 void MdssRot::doTransform() { 108 if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) 109 utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h); 110 } 111 112 bool MdssRot::commit() { 113 doTransform(); 114 mRotInfo.flags |= MDSS_MDP_ROT_ONLY; 115 mEnabled = true; 116 if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) { 117 ALOGE("MdssRot commit failed!"); 118 dump(); 119 return (mEnabled = false); 120 } 121 mRotData.id = mRotInfo.id; 122 return true; 123 } 124 125 bool MdssRot::queueBuffer(int fd, uint32_t offset) { 126 if(enabled()) { 127 mRotData.data.memory_id = fd; 128 mRotData.data.offset = offset; 129 130 remap(RotMem::Mem::ROT_NUM_BUFS); 131 OVASSERT(mMem.curr().m.numBufs(), "queueBuffer numbufs is 0"); 132 133 mRotData.dst_data.offset = 134 mMem.curr().mRotOffset[mMem.curr().mCurrOffset]; 135 mMem.curr().mCurrOffset = 136 (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs(); 137 138 if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) { 139 ALOGE("MdssRot play failed!"); 140 dump(); 141 return false; 142 } 143 144 // if the prev mem is valid, we need to close 145 if(mMem.prev().valid()) { 146 // FIXME if no wait for vsync the above 147 // play will return immediatly and might cause 148 // tearing when prev.close is called. 149 if(!mMem.prev().close()) { 150 ALOGE("%s error in closing prev rot mem", __FUNCTION__); 151 return false; 152 } 153 } 154 } 155 return true; 156 } 157 158 bool MdssRot::open_i(uint32_t numbufs, uint32_t bufsz) 159 { 160 OvMem mem; 161 OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i"); 162 bool isSecure = mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION; 163 164 if(!mem.open(numbufs, bufsz, isSecure)){ 165 ALOGE("%s: Failed to open", __func__); 166 mem.close(); 167 return false; 168 } 169 170 OVASSERT(MAP_FAILED != mem.addr(), "MAP failed"); 171 OVASSERT(mem.getFD() != -1, "getFd is -1"); 172 173 mRotData.dst_data.memory_id = mem.getFD(); 174 mRotData.dst_data.offset = 0; 175 mMem.curr().m = mem; 176 return true; 177 } 178 179 bool MdssRot::remap(uint32_t numbufs) { 180 // Calculate the size based on rotator's dst format, w and h. 181 uint32_t opBufSize = calcOutputBufSize(); 182 // If current size changed, remap 183 if(opBufSize == mMem.curr().size()) { 184 ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize); 185 return true; 186 } 187 188 ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__); 189 OVASSERT(!mMem.prev().valid(), "Prev should not be valid"); 190 191 // ++mMem will make curr to be prev, and prev will be curr 192 ++mMem; 193 if(!open_i(numbufs, opBufSize)) { 194 ALOGE("%s Error could not open", __FUNCTION__); 195 return false; 196 } 197 for (uint32_t i = 0; i < numbufs; ++i) { 198 mMem.curr().mRotOffset[i] = i * opBufSize; 199 } 200 return true; 201 } 202 203 bool MdssRot::close() { 204 bool success = true; 205 if(mFd.valid() && (getSessId() != (uint32_t) MSMFB_NEW_REQUEST)) { 206 if(!mdp_wrapper::unsetOverlay(mFd.getFD(), getSessId())) { 207 ALOGE("MdssRot::close unsetOverlay failed, fd=%d sessId=%d", 208 mFd.getFD(), getSessId()); 209 success = false; 210 } 211 } 212 213 if (!mFd.close()) { 214 ALOGE("Mdss Rot error closing fd"); 215 success = false; 216 } 217 if (!mMem.close()) { 218 ALOGE("Mdss Rot error closing mem"); 219 success = false; 220 } 221 reset(); 222 return success; 223 } 224 225 void MdssRot::reset() { 226 ovutils::memset0(mRotInfo); 227 ovutils::memset0(mRotData); 228 mRotData.data.memory_id = -1; 229 mRotInfo.id = MSMFB_NEW_REQUEST; 230 ovutils::memset0(mMem.curr().mRotOffset); 231 ovutils::memset0(mMem.prev().mRotOffset); 232 mMem.curr().mCurrOffset = 0; 233 mMem.prev().mCurrOffset = 0; 234 mOrientation = utils::OVERLAY_TRANSFORM_0; 235 } 236 237 void MdssRot::dump() const { 238 ALOGE("== Dump MdssRot start =="); 239 mFd.dump(); 240 mMem.curr().m.dump(); 241 mdp_wrapper::dump("mRotInfo", mRotInfo); 242 mdp_wrapper::dump("mRotData", mRotData); 243 ALOGE("== Dump MdssRot end =="); 244 } 245 246 uint32_t MdssRot::calcOutputBufSize() { 247 uint32_t opBufSize = 0; 248 ovutils::Whf destWhf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h, 249 mRotInfo.src.format); //mdss src and dst formats are same. 250 251 opBufSize = Rotator::calcOutputBufSize(destWhf); 252 253 if (mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION) 254 opBufSize = utils::align(opBufSize, SIZE_1M); 255 256 return opBufSize; 257 } 258 259 void MdssRot::getDump(char *buf, size_t len) const { 260 ovutils::getDump(buf, len, "MdssRotCtrl(mdp_overlay)", mRotInfo); 261 ovutils::getDump(buf, len, "MdssRotData(msmfb_overlay_data)", mRotData); 262 } 263 264 } // namespace overlay 265