1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * Copyright (c) 2010-2014, 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 MDSS_ROT_MASK (MDP_ROT_90 | MDP_FLIP_UD | MDP_FLIP_LR) 36 37 namespace ovutils = overlay::utils; 38 39 namespace overlay { 40 using namespace utils; 41 42 MdssRot::MdssRot() { 43 reset(); 44 init(); 45 } 46 47 MdssRot::~MdssRot() { close(); } 48 49 bool MdssRot::enabled() const { return mEnabled; } 50 51 void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; } 52 53 int MdssRot::getDstMemId() const { 54 return mRotData.dst_data.memory_id; 55 } 56 57 uint32_t MdssRot::getDstOffset() const { 58 return mRotData.dst_data.offset; 59 } 60 61 uint32_t MdssRot::getDstFormat() const { 62 //For mdss src and dst formats are same 63 return mRotInfo.src.format; 64 } 65 66 uint32_t MdssRot::getSessId() const { return mRotInfo.id; } 67 68 bool MdssRot::init() { 69 if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) { 70 ALOGE("MdssRot failed to init fb0"); 71 return false; 72 } 73 return true; 74 } 75 76 void MdssRot::setSource(const overlay::utils::Whf& awhf) { 77 utils::Whf whf(awhf); 78 79 mRotInfo.src.format = whf.format; 80 mRotInfo.src.width = whf.w; 81 mRotInfo.src.height = whf.h; 82 } 83 84 void MdssRot::setCrop(const utils::Dim& crop) { 85 86 mRotInfo.src_rect.x = crop.x; 87 mRotInfo.src_rect.y = crop.y; 88 mRotInfo.src_rect.w = crop.w; 89 mRotInfo.src_rect.h = crop.h; 90 91 mRotInfo.dst_rect.x = 0; 92 mRotInfo.dst_rect.y = 0; 93 mRotInfo.dst_rect.w = crop.w; 94 mRotInfo.dst_rect.h = crop.h; 95 } 96 97 void MdssRot::setDownscale(int /*ds*/) { 98 } 99 100 void MdssRot::setFlags(const utils::eMdpFlags& flags) { 101 mRotInfo.flags = flags; 102 } 103 104 void MdssRot::setTransform(const utils::eTransform& rot) 105 { 106 // reset rotation flags to avoid stale orientation values 107 mRotInfo.flags &= ~MDSS_ROT_MASK; 108 int flags = utils::getMdpOrient(rot); 109 if (flags != -1) 110 setRotations(flags); 111 mOrientation = static_cast<utils::eTransform>(flags); 112 ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags); 113 } 114 115 void MdssRot::doTransform() { 116 mRotInfo.flags |= mOrientation; 117 if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) 118 utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h); 119 } 120 121 bool MdssRot::commit() { 122 doTransform(); 123 mRotInfo.flags |= MDSS_MDP_ROT_ONLY; 124 mEnabled = true; 125 if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) { 126 ALOGE("MdssRot commit failed!"); 127 dump(); 128 return (mEnabled = false); 129 } 130 mRotData.id = mRotInfo.id; 131 return true; 132 } 133 134 bool MdssRot::queueBuffer(int fd, uint32_t offset) { 135 if(enabled()) { 136 mRotData.data.memory_id = fd; 137 mRotData.data.offset = offset; 138 139 if(false == remap(RotMem::ROT_NUM_BUFS)) { 140 ALOGE("%s Remap failed, not queuing", __FUNCTION__); 141 return false; 142 } 143 144 mRotData.dst_data.offset = 145 mMem.mRotOffset[mMem.mCurrIndex]; 146 mMem.mCurrIndex = 147 (mMem.mCurrIndex + 1) % mMem.mem.numBufs(); 148 149 if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) { 150 ALOGE("MdssRot play failed!"); 151 dump(); 152 return false; 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.mem = 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.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 190 if(!mMem.close()) { 191 ALOGE("%s error in closing prev rot mem", __FUNCTION__); 192 return false; 193 } 194 195 if(!open_i(numbufs, opBufSize)) { 196 ALOGE("%s Error could not open", __FUNCTION__); 197 return false; 198 } 199 200 for (uint32_t i = 0; i < numbufs; ++i) { 201 mMem.mRotOffset[i] = i * opBufSize; 202 } 203 204 return true; 205 } 206 207 bool MdssRot::close() { 208 bool success = true; 209 if(mFd.valid() && (getSessId() != (uint32_t) MSMFB_NEW_REQUEST)) { 210 if(!mdp_wrapper::unsetOverlay(mFd.getFD(), getSessId())) { 211 ALOGE("MdssRot::close unsetOverlay failed, fd=%d sessId=%d", 212 mFd.getFD(), getSessId()); 213 success = false; 214 } 215 } 216 217 if (!mFd.close()) { 218 ALOGE("Mdss Rot error closing fd"); 219 success = false; 220 } 221 if (!mMem.close()) { 222 ALOGE("Mdss Rot error closing mem"); 223 success = false; 224 } 225 reset(); 226 return success; 227 } 228 229 void MdssRot::reset() { 230 ovutils::memset0(mRotInfo); 231 ovutils::memset0(mRotData); 232 mRotData.data.memory_id = -1; 233 mRotInfo.id = MSMFB_NEW_REQUEST; 234 ovutils::memset0(mMem.mRotOffset); 235 mMem.mCurrIndex = 0; 236 mOrientation = utils::OVERLAY_TRANSFORM_0; 237 } 238 239 void MdssRot::dump() const { 240 ALOGE("== Dump MdssRot start =="); 241 mFd.dump(); 242 mMem.mem.dump(); 243 mdp_wrapper::dump("mRotInfo", mRotInfo); 244 mdp_wrapper::dump("mRotData", mRotData); 245 ALOGE("== Dump MdssRot end =="); 246 } 247 248 uint32_t MdssRot::calcOutputBufSize() { 249 uint32_t opBufSize = 0; 250 ovutils::Whf destWhf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h, 251 mRotInfo.src.format); //mdss src and dst formats are same. 252 253 if (mRotInfo.flags & ovutils::OV_MDSS_MDP_BWC_EN) { 254 opBufSize = calcCompressedBufSize(destWhf); 255 } else { 256 opBufSize = Rotator::calcOutputBufSize(destWhf); 257 } 258 259 return opBufSize; 260 } 261 262 void MdssRot::getDump(char *buf, size_t len) const { 263 ovutils::getDump(buf, len, "MdssRotCtrl", mRotInfo); 264 ovutils::getDump(buf, len, "MdssRotData", mRotData); 265 } 266 267 // Calculate the compressed o/p buffer size for BWC 268 uint32_t MdssRot::calcCompressedBufSize(const ovutils::Whf& destWhf) { 269 uint32_t bufSize = 0; 270 //Worst case alignments 271 int aWidth = ovutils::align(destWhf.w, 64); 272 int aHeight = ovutils::align(destWhf.h, 4); 273 /* 274 Format | RAU size (width x height) 275 ---------------------------------------------- 276 ARGB | 32 pixel x 4 line 277 RGB888 | 32 pixel x 4 line 278 Y (Luma) | 64 pixel x 4 line 279 CRCB 420 | 32 pixel x 2 line 280 CRCB 422 H2V1 | 32 pixel x 4 line 281 CRCB 422 H1V2 | 64 pixel x 2 line 282 283 Metadata requirements:- 284 1 byte meta data for every 8 RAUs 285 2 byte meta data per RAU 286 */ 287 288 //These blocks attempt to allocate for the worst case in each of the 289 //respective format classes, yuv/rgb. The table above is for reference 290 if(utils::isYuv(destWhf.format)) { 291 int yRauCount = aWidth / 64; //Y 292 int cRauCount = aWidth / 32; //C 293 int yStride = (64 * 4 * yRauCount) + alignup(yRauCount, 8) / 8; 294 int cStride = ((32 * 2 * cRauCount) + alignup(cRauCount, 8) / 8) * 2; 295 int yStrideOffset = (aHeight / 4); 296 int cStrideOffset = (aHeight / 2); 297 bufSize = (yStride * yStrideOffset + cStride * cStrideOffset) + 298 (yRauCount * yStrideOffset * 2) + 299 (cRauCount * cStrideOffset * 2) * 2; 300 ALOGD_IF(DEBUG_MDSS_ROT, "%s:YUV Y RAU Count = %d C RAU Count = %d", 301 __FUNCTION__, yRauCount, cRauCount); 302 } else { 303 int rauCount = aWidth / 32; 304 //Single plane 305 int stride = (32 * 4 * rauCount) + alignup(rauCount, 8) / 8; 306 int strideOffset = (aHeight / 4); 307 bufSize = (stride * strideOffset * 4 /*bpp*/) + 308 (rauCount * strideOffset * 2); 309 ALOGD_IF(DEBUG_MDSS_ROT, "%s:RGB RAU count = %d", __FUNCTION__, 310 rauCount); 311 } 312 313 ALOGD_IF(DEBUG_MDSS_ROT, "%s: aligned width = %d, aligned height = %d " 314 "Buf Size = %d", __FUNCTION__, aWidth, aHeight, bufSize); 315 316 return bufSize; 317 } 318 319 } // namespace overlay 320