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 #include "gr.h"
     23 
     24 namespace ovutils = overlay::utils;
     25 
     26 namespace overlay {
     27 
     28 MdpRot::MdpRot() {
     29     reset();
     30     init();
     31 }
     32 
     33 MdpRot::~MdpRot() { close(); }
     34 
     35 bool MdpRot::enabled() const { return mRotImgInfo.enable; }
     36 
     37 void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = (uint8_t)r; }
     38 
     39 int MdpRot::getDstMemId() const {
     40     return mRotDataInfo.dst.memory_id;
     41 }
     42 
     43 uint32_t MdpRot::getDstOffset() const {
     44     return mRotDataInfo.dst.offset;
     45 }
     46 
     47 uint32_t MdpRot::getDstFormat() const {
     48     return mRotImgInfo.dst.format;
     49 }
     50 
     51 //Added for completeness. Not expected to be called.
     52 utils::Whf MdpRot::getDstWhf() const {
     53     int alW = 0, alH = 0;
     54     int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
     55     getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
     56             halFormat, alW, alH);
     57     return utils::Whf(alW, alH, mRotImgInfo.dst.format);
     58 }
     59 
     60 //Added for completeness. Not expected to be called.
     61 utils::Dim MdpRot::getDstDimensions() const {
     62     int alW = 0, alH = 0;
     63     int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
     64     getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
     65             halFormat, alW, alH);
     66     return utils::Dim(0, 0, alW, alH);
     67 }
     68 
     69 uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; }
     70 
     71 void MdpRot::setDownscale(int ds) {
     72     if ((utils::ROT_DS_EIGHTH == ds) && (mRotImgInfo.src_rect.h & 0xF)) {
     73         // Ensure src_rect.h is a multiple of 16 for 1/8 downscaling.
     74         // This is an undocumented MDP Rotator constraint.
     75         mRotImgInfo.src_rect.h = utils::aligndown(mRotImgInfo.src_rect.h, 16);
     76     }
     77     mRotImgInfo.downscale_ratio = ds;
     78 }
     79 
     80 void MdpRot::save() {
     81     mLSRotImgInfo = mRotImgInfo;
     82 }
     83 
     84 bool MdpRot::rotConfChanged() const {
     85     // 0 means same
     86     if(0 == ::memcmp(&mRotImgInfo, &mLSRotImgInfo,
     87                 sizeof (msm_rotator_img_info))) {
     88         return false;
     89     }
     90     return true;
     91 }
     92 
     93 bool MdpRot::init()
     94 {
     95     if(!mFd.open(Res::rotPath, O_RDWR)){
     96         ALOGE("MdpRot failed to init %s", Res::rotPath);
     97         return false;
     98     }
     99     return true;
    100 }
    101 
    102 void MdpRot::setSource(const overlay::utils::Whf& awhf) {
    103     utils::Whf whf(awhf);
    104     mRotImgInfo.src.format = whf.format;
    105 
    106     mRotImgInfo.src.width = whf.w;
    107     mRotImgInfo.src.height = whf.h;
    108 
    109     mRotImgInfo.src_rect.w = whf.w;
    110     mRotImgInfo.src_rect.h = whf.h;
    111 
    112     mRotImgInfo.dst.width = whf.w;
    113     mRotImgInfo.dst.height = whf.h;
    114 }
    115 
    116 void MdpRot::setCrop(const utils::Dim& /*crop*/) {
    117     // NO-OP for non-mdss rotator due to possible h/w limitations
    118 }
    119 
    120 void MdpRot::setFlags(const utils::eMdpFlags& flags) {
    121     mRotImgInfo.secure = 0;
    122     if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
    123         mRotImgInfo.secure = 1;
    124 }
    125 
    126 void MdpRot::setTransform(const utils::eTransform& rot)
    127 {
    128     int r = utils::getMdpOrient(rot);
    129     setRotations(r);
    130     mOrientation = static_cast<utils::eTransform>(r);
    131     ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r);
    132 }
    133 
    134 void MdpRot::doTransform() {
    135     if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90)
    136         utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height);
    137 }
    138 
    139 bool MdpRot::commit() {
    140     doTransform();
    141     if(rotConfChanged()) {
    142         mRotImgInfo.enable = 1;
    143         if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) {
    144             ALOGE("MdpRot commit failed");
    145             dump();
    146             mRotImgInfo.enable = 0;
    147             return false;
    148         }
    149         save();
    150         mRotDataInfo.session_id = mRotImgInfo.session_id;
    151     }
    152     return true;
    153 }
    154 
    155 uint32_t MdpRot::calcOutputBufSize() {
    156     ovutils::Whf destWhf(mRotImgInfo.dst.width,
    157             mRotImgInfo.dst.height, mRotImgInfo.dst.format);
    158     return Rotator::calcOutputBufSize(destWhf);
    159 }
    160 
    161 bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz)
    162 {
    163     OvMem mem;
    164 
    165     OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
    166 
    167     if(!mem.open(numbufs, bufsz, mRotImgInfo.secure)){
    168         ALOGE("%s: Failed to open", __func__);
    169         mem.close();
    170         return false;
    171     }
    172 
    173     OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
    174     OVASSERT(mem.getFD() != -1, "getFd is -1");
    175 
    176     mRotDataInfo.dst.memory_id = mem.getFD();
    177     mRotDataInfo.dst.offset = 0;
    178     mMem.mem = mem;
    179     return true;
    180 }
    181 
    182 bool MdpRot::close() {
    183     bool success = true;
    184     if(mFd.valid() && (getSessId() != 0)) {
    185         if(!mdp_wrapper::endRotator(mFd.getFD(), getSessId())) {
    186             ALOGE("Mdp Rot error endRotator, fd=%d sessId=%u",
    187                     mFd.getFD(), getSessId());
    188             success = false;
    189         }
    190     }
    191     if (!mFd.close()) {
    192         ALOGE("Mdp Rot error closing fd");
    193         success = false;
    194     }
    195     if (!mMem.close()) {
    196         ALOGE("Mdp Rot error closing mem");
    197         success = false;
    198     }
    199     reset();
    200     return success;
    201 }
    202 
    203 bool MdpRot::remap(uint32_t numbufs) {
    204     // if current size changed, remap
    205     uint32_t opBufSize = calcOutputBufSize();
    206     if(opBufSize == mMem.size()) {
    207         ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize);
    208         return true;
    209     }
    210 
    211     if(!mMem.close()) {
    212         ALOGE("%s error in closing prev rot mem", __FUNCTION__);
    213         return false;
    214     }
    215 
    216     ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
    217 
    218     if(!open_i(numbufs, opBufSize)) {
    219         ALOGE("%s Error could not open", __FUNCTION__);
    220         return false;
    221     }
    222 
    223     for (uint32_t i = 0; i < numbufs; ++i) {
    224         mMem.mRotOffset[i] = i * opBufSize;
    225     }
    226 
    227     return true;
    228 }
    229 
    230 void MdpRot::reset() {
    231     ovutils::memset0(mRotImgInfo);
    232     ovutils::memset0(mLSRotImgInfo);
    233     ovutils::memset0(mRotDataInfo);
    234     ovutils::memset0(mMem.mRotOffset);
    235     mMem.mCurrIndex = 0;
    236     mOrientation = utils::OVERLAY_TRANSFORM_0;
    237 }
    238 
    239 bool MdpRot::queueBuffer(int fd, uint32_t offset) {
    240     if(enabled()) {
    241         mRotDataInfo.src.memory_id = fd;
    242         mRotDataInfo.src.offset = offset;
    243 
    244         if(false == remap(RotMem::ROT_NUM_BUFS)) {
    245             ALOGE("%s Remap failed, not queueing", __FUNCTION__);
    246             return false;
    247         }
    248 
    249         mRotDataInfo.dst.offset =
    250                 mMem.mRotOffset[mMem.mCurrIndex];
    251         mMem.mCurrIndex =
    252                 (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
    253 
    254         if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) {
    255             ALOGE("MdpRot failed rotate");
    256             dump();
    257             return false;
    258         }
    259     }
    260     return true;
    261 }
    262 
    263 void MdpRot::dump() const {
    264     ALOGE("== Dump MdpRot start ==");
    265     mFd.dump();
    266     mMem.mem.dump();
    267     mdp_wrapper::dump("mRotImgInfo", mRotImgInfo);
    268     mdp_wrapper::dump("mRotDataInfo", mRotDataInfo);
    269     ALOGE("== Dump MdpRot end ==");
    270 }
    271 
    272 void MdpRot::getDump(char *buf, size_t len) const {
    273     ovutils::getDump(buf, len, "MdpRotCtrl", mRotImgInfo);
    274     ovutils::getDump(buf, len, "MdpRotData", mRotDataInfo);
    275 }
    276 
    277 } // namespace overlay
    278