Home | History | Annotate | Download | only in liboverlay
      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