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 utils::Whf MdssRot::getDstWhf() const { 67 //For Mdss dst_rect itself represents buffer dimensions. We ignore actual 68 //aligned values during buffer allocation. Also the driver overwrites the 69 //src.format field if destination format is different. 70 //This implementation detail makes it possible to retrieve w,h even before 71 //buffer allocation, which happens in queueBuffer. 72 return utils::Whf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h, 73 mRotInfo.src.format); 74 } 75 76 utils::Dim MdssRot::getDstDimensions() const { 77 return utils::Dim(mRotInfo.dst_rect.x, mRotInfo.dst_rect.y, 78 mRotInfo.dst_rect.w, mRotInfo.dst_rect.h); 79 } 80 81 uint32_t MdssRot::getSessId() const { return mRotInfo.id; } 82 83 bool MdssRot::init() { 84 if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) { 85 ALOGE("MdssRot failed to init fb0"); 86 return false; 87 } 88 return true; 89 } 90 91 void MdssRot::setSource(const overlay::utils::Whf& awhf) { 92 utils::Whf whf(awhf); 93 94 mRotInfo.src.format = whf.format; 95 mRotInfo.src.width = whf.w; 96 mRotInfo.src.height = whf.h; 97 } 98 99 void MdssRot::setCrop(const utils::Dim& crop) { 100 mRotInfo.src_rect.x = crop.x; 101 mRotInfo.src_rect.y = crop.y; 102 mRotInfo.src_rect.w = crop.w; 103 mRotInfo.src_rect.h = crop.h; 104 } 105 106 void MdssRot::setDownscale(int /*ds*/) { 107 } 108 109 void MdssRot::setFlags(const utils::eMdpFlags& flags) { 110 mRotInfo.flags = flags; 111 } 112 113 void MdssRot::setTransform(const utils::eTransform& rot) 114 { 115 // reset rotation flags to avoid stale orientation values 116 mRotInfo.flags &= ~MDSS_ROT_MASK; 117 int flags = utils::getMdpOrient(rot); 118 if (flags != -1) 119 setRotations(flags); 120 mOrientation = static_cast<utils::eTransform>(flags); 121 ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags); 122 } 123 124 void MdssRot::doTransform() { 125 mRotInfo.flags |= mOrientation; 126 if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) 127 utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h); 128 } 129 130 bool MdssRot::commit() { 131 if (utils::isYuv(mRotInfo.src.format)) { 132 utils::normalizeCrop(mRotInfo.src_rect.x, mRotInfo.src_rect.w); 133 utils::normalizeCrop(mRotInfo.src_rect.y, mRotInfo.src_rect.h); 134 // For interlaced, crop.h should be 4-aligned 135 if ((mRotInfo.flags & utils::OV_MDP_DEINTERLACE) and 136 (mRotInfo.src_rect.h % 4)) 137 mRotInfo.src_rect.h = utils::aligndown(mRotInfo.src_rect.h, 4); 138 } 139 140 mRotInfo.dst_rect.x = 0; 141 mRotInfo.dst_rect.y = 0; 142 mRotInfo.dst_rect.w = mRotInfo.src_rect.w; 143 mRotInfo.dst_rect.h = mRotInfo.src_rect.h; 144 145 doTransform(); 146 147 mRotInfo.flags |= MDSS_MDP_ROT_ONLY; 148 mEnabled = true; 149 if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) { 150 ALOGE("MdssRot commit failed!"); 151 dump(); 152 return (mEnabled = false); 153 } 154 mRotData.id = mRotInfo.id; 155 return true; 156 } 157 158 bool MdssRot::queueBuffer(int fd, uint32_t offset) { 159 if(enabled()) { 160 mRotData.data.memory_id = fd; 161 mRotData.data.offset = offset; 162 163 if(false == remap(RotMem::ROT_NUM_BUFS)) { 164 ALOGE("%s Remap failed, not queuing", __FUNCTION__); 165 return false; 166 } 167 168 mRotData.dst_data.offset = 169 mMem.mRotOffset[mMem.mCurrIndex]; 170 mMem.mCurrIndex = 171 (mMem.mCurrIndex + 1) % mMem.mem.numBufs(); 172 173 if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) { 174 ALOGE("MdssRot play failed!"); 175 dump(); 176 return false; 177 } 178 } 179 return true; 180 } 181 182 bool MdssRot::open_i(uint32_t numbufs, uint32_t bufsz) 183 { 184 OvMem mem; 185 OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i"); 186 bool isSecure = mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION; 187 188 if(!mem.open(numbufs, bufsz, isSecure)){ 189 ALOGE("%s: Failed to open", __func__); 190 mem.close(); 191 return false; 192 } 193 194 OVASSERT(MAP_FAILED != mem.addr(), "MAP failed"); 195 OVASSERT(mem.getFD() != -1, "getFd is -1"); 196 197 mRotData.dst_data.memory_id = mem.getFD(); 198 mRotData.dst_data.offset = 0; 199 mMem.mem = mem; 200 return true; 201 } 202 203 bool MdssRot::remap(uint32_t numbufs) { 204 // Calculate the size based on rotator's dst format, w and h. 205 uint32_t opBufSize = calcOutputBufSize(); 206 // If current size changed, remap 207 if(opBufSize == mMem.size()) { 208 ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize); 209 return true; 210 } 211 212 ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__); 213 214 if(!mMem.close()) { 215 ALOGE("%s error in closing prev rot mem", __FUNCTION__); 216 return false; 217 } 218 219 if(!open_i(numbufs, opBufSize)) { 220 ALOGE("%s Error could not open", __FUNCTION__); 221 return false; 222 } 223 224 for (uint32_t i = 0; i < numbufs; ++i) { 225 mMem.mRotOffset[i] = i * opBufSize; 226 } 227 228 return true; 229 } 230 231 bool MdssRot::close() { 232 bool success = true; 233 if(mFd.valid() && (getSessId() != (uint32_t) MSMFB_NEW_REQUEST)) { 234 if(!mdp_wrapper::unsetOverlay(mFd.getFD(), getSessId())) { 235 ALOGE("MdssRot::close unsetOverlay failed, fd=%d sessId=%d", 236 mFd.getFD(), getSessId()); 237 success = false; 238 } 239 } 240 241 if (!mFd.close()) { 242 ALOGE("Mdss Rot error closing fd"); 243 success = false; 244 } 245 if (!mMem.close()) { 246 ALOGE("Mdss Rot error closing mem"); 247 success = false; 248 } 249 reset(); 250 return success; 251 } 252 253 void MdssRot::reset() { 254 ovutils::memset0(mRotInfo); 255 ovutils::memset0(mRotData); 256 mRotData.data.memory_id = -1; 257 mRotInfo.id = MSMFB_NEW_REQUEST; 258 ovutils::memset0(mMem.mRotOffset); 259 mMem.mCurrIndex = 0; 260 mOrientation = utils::OVERLAY_TRANSFORM_0; 261 } 262 263 void MdssRot::dump() const { 264 ALOGE("== Dump MdssRot start =="); 265 mFd.dump(); 266 mMem.mem.dump(); 267 mdp_wrapper::dump("mRotInfo", mRotInfo); 268 mdp_wrapper::dump("mRotData", mRotData); 269 ALOGE("== Dump MdssRot end =="); 270 } 271 272 uint32_t MdssRot::calcOutputBufSize() { 273 uint32_t opBufSize = 0; 274 ovutils::Whf destWhf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h, 275 mRotInfo.src.format); //mdss src and dst formats are same. 276 277 if (mRotInfo.flags & ovutils::OV_MDSS_MDP_BWC_EN) { 278 opBufSize = calcCompressedBufSize(destWhf); 279 } else { 280 opBufSize = Rotator::calcOutputBufSize(destWhf); 281 } 282 283 return opBufSize; 284 } 285 286 void MdssRot::getDump(char *buf, size_t len) const { 287 ovutils::getDump(buf, len, "MdssRotCtrl", mRotInfo); 288 ovutils::getDump(buf, len, "MdssRotData", mRotData); 289 } 290 291 // Calculate the compressed o/p buffer size for BWC 292 uint32_t MdssRot::calcCompressedBufSize(const ovutils::Whf& destWhf) { 293 uint32_t bufSize = 0; 294 //Worst case alignments 295 int aWidth = ovutils::align(destWhf.w, 64); 296 int aHeight = ovutils::align(destWhf.h, 4); 297 /* 298 Format | RAU size (width x height) 299 ---------------------------------------------- 300 ARGB | 32 pixel x 4 line 301 RGB888 | 32 pixel x 4 line 302 Y (Luma) | 64 pixel x 4 line 303 CRCB 420 | 32 pixel x 2 line 304 CRCB 422 H2V1 | 32 pixel x 4 line 305 CRCB 422 H1V2 | 64 pixel x 2 line 306 307 Metadata requirements:- 308 1 byte meta data for every 8 RAUs 309 2 byte meta data per RAU 310 */ 311 312 //These blocks attempt to allocate for the worst case in each of the 313 //respective format classes, yuv/rgb. The table above is for reference 314 if(utils::isYuv(destWhf.format)) { 315 int yRauCount = aWidth / 64; //Y 316 int cRauCount = aWidth / 32; //C 317 int yStride = (64 * 4 * yRauCount) + alignup(yRauCount, 8) / 8; 318 int cStride = ((32 * 2 * cRauCount) + alignup(cRauCount, 8) / 8) * 2; 319 int yStrideOffset = (aHeight / 4); 320 int cStrideOffset = (aHeight / 2); 321 bufSize = (yStride * yStrideOffset + cStride * cStrideOffset) + 322 (yRauCount * yStrideOffset * 2) + 323 (cRauCount * cStrideOffset * 2) * 2; 324 ALOGD_IF(DEBUG_MDSS_ROT, "%s:YUV Y RAU Count = %d C RAU Count = %d", 325 __FUNCTION__, yRauCount, cRauCount); 326 } else { 327 int rauCount = aWidth / 32; 328 //Single plane 329 int stride = (32 * 4 * rauCount) + alignup(rauCount, 8) / 8; 330 int strideOffset = (aHeight / 4); 331 bufSize = (stride * strideOffset * 4 /*bpp*/) + 332 (rauCount * strideOffset * 2); 333 ALOGD_IF(DEBUG_MDSS_ROT, "%s:RGB RAU count = %d", __FUNCTION__, 334 rauCount); 335 } 336 337 ALOGD_IF(DEBUG_MDSS_ROT, "%s: aligned width = %d, aligned height = %d " 338 "Buf Size = %d", __FUNCTION__, aWidth, aHeight, bufSize); 339 340 return bufSize; 341 } 342 343 } // namespace overlay 344