Home | History | Annotate | Download | only in pipes
      1 /*
      2 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
      3 *
      4 * Redistribution and use in source and binary forms, with or without
      5 * modification, are permitted provided that the following conditions are
      6 * met:
      7 *    * Redistributions of source code must retain the above copyright
      8 *      notice, this list of conditions and the following disclaimer.
      9 *    * Redistributions in binary form must reproduce the above
     10 *      copyright notice, this list of conditions and the following
     11 *      disclaimer in the documentation and/or other materials provided
     12 *      with the distribution.
     13 *    * Neither the name of The Linux Foundation nor the names of its
     14 *      contributors may be used to endorse or promote products derived
     15 *      from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 
     30 #include "overlayGenPipe.h"
     31 #include "overlay.h"
     32 #include "mdp_version.h"
     33 
     34 namespace overlay {
     35 
     36 GenericPipe::GenericPipe(int dpy) : mFbNum(dpy), mRot(0), mRotUsed(false),
     37         mRotDownscaleOpt(false), mPreRotated(false), pipeState(CLOSED) {
     38     init();
     39 }
     40 
     41 GenericPipe::~GenericPipe() {
     42     close();
     43 }
     44 
     45 bool GenericPipe::init()
     46 {
     47     ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init");
     48     mRotUsed = false;
     49     mRotDownscaleOpt = false;
     50     mPreRotated = false;
     51     if(mFbNum)
     52         mFbNum = Overlay::getInstance()->getExtFbNum();
     53 
     54     ALOGD_IF(DEBUG_OVERLAY,"%s: mFbNum:%d",__FUNCTION__, mFbNum);
     55 
     56     if(!mCtrlData.ctrl.init(mFbNum)) {
     57         ALOGE("GenericPipe failed to init ctrl");
     58         return false;
     59     }
     60 
     61     if(!mCtrlData.data.init(mFbNum)) {
     62         ALOGE("GenericPipe failed to init data");
     63         return false;
     64     }
     65 
     66     //get a new rotator object, take ownership
     67     mRot = Rotator::getRotator();
     68 
     69     return true;
     70 }
     71 
     72 bool GenericPipe::close() {
     73     bool ret = true;
     74 
     75     if(!mCtrlData.ctrl.close()) {
     76         ALOGE("GenericPipe failed to close ctrl");
     77         ret = false;
     78     }
     79     if (!mCtrlData.data.close()) {
     80         ALOGE("GenericPipe failed to close data");
     81         ret = false;
     82     }
     83 
     84     delete mRot;
     85     mRot = 0;
     86 
     87     setClosed();
     88     return ret;
     89 }
     90 
     91 void GenericPipe::setSource(const utils::PipeArgs& args) {
     92     //Cache if user wants 0-rotation
     93     mRotUsed = args.rotFlags & utils::ROT_0_ENABLED;
     94     mRotDownscaleOpt = args.rotFlags & utils::ROT_DOWNSCALE_ENABLED;
     95     mPreRotated = args.rotFlags & utils::ROT_PREROTATED;
     96     if(mPreRotated) mRotUsed = false;
     97     mRot->setSource(args.whf);
     98     mRot->setFlags(args.mdpFlags);
     99     mCtrlData.ctrl.setSource(args);
    100 }
    101 
    102 void GenericPipe::setCrop(const overlay::utils::Dim& d) {
    103     mCtrlData.ctrl.setCrop(d);
    104 }
    105 
    106 void GenericPipe::setTransform(const utils::eTransform& orient) {
    107     //Rotation could be enabled by user for zero-rot or the layer could have
    108     //some transform. Mark rotation enabled in either case.
    109     mRotUsed |= ((orient & utils::OVERLAY_TRANSFORM_ROT_90) && !mPreRotated);
    110     mRot->setTransform(orient);
    111     mCtrlData.ctrl.setTransform(orient);
    112 }
    113 
    114 void GenericPipe::setPosition(const utils::Dim& d) {
    115     mCtrlData.ctrl.setPosition(d);
    116 }
    117 
    118 bool GenericPipe::setVisualParams(const MetaData_t &metadata)
    119 {
    120         return mCtrlData.ctrl.setVisualParams(metadata);
    121 }
    122 
    123 bool GenericPipe::commit() {
    124     bool ret = false;
    125     int downscale_factor = utils::ROT_DS_NONE;
    126 
    127     if(mRotDownscaleOpt) {
    128         ovutils::Dim src(mCtrlData.ctrl.getCrop());
    129         ovutils::Dim dst(mCtrlData.ctrl.getPosition());
    130         downscale_factor = ovutils::getDownscaleFactor(
    131                 src.w, src.h, dst.w, dst.h);
    132         mRotUsed |= (downscale_factor && !mPreRotated);
    133     }
    134 
    135 
    136     if(mRotUsed) {
    137         mRot->setDownscale(downscale_factor);
    138         //If wanting to use rotator, start it.
    139         if(!mRot->commit()) {
    140             ALOGE("GenPipe Rotator commit failed");
    141             //If rot commit fails, flush rotator session, memory, fd and create
    142             //a hollow rotator object
    143             delete mRot;
    144             mRot = Rotator::getRotator();
    145             pipeState = CLOSED;
    146             return false;
    147         }
    148         /* Set the mdp src format to the output format of the rotator.
    149          * The output format of the rotator might be different depending on
    150          * whether fastyuv mode is enabled in the rotator.
    151          */
    152         mCtrlData.ctrl.updateSrcFormat(mRot->getDstFormat());
    153     }
    154 
    155     mCtrlData.ctrl.setDownscale(downscale_factor);
    156     ret = mCtrlData.ctrl.commit();
    157 
    158     //If mdp commit fails, flush rotator session, memory, fd and create a hollow
    159     //rotator object
    160     if(ret == false) {
    161         delete mRot;
    162         mRot = Rotator::getRotator();
    163     }
    164 
    165     pipeState = ret ? OPEN : CLOSED;
    166     return ret;
    167 }
    168 
    169 bool GenericPipe::queueBuffer(int fd, uint32_t offset) {
    170     //TODO Move pipe-id transfer to CtrlData class. Make ctrl and data private.
    171     OVASSERT(isOpen(), "State is closed, cannot queueBuffer");
    172     int pipeId = mCtrlData.ctrl.getPipeId();
    173     OVASSERT(-1 != pipeId, "Ctrl ID should not be -1");
    174     // set pipe id from ctrl to data
    175     mCtrlData.data.setPipeId(pipeId);
    176 
    177     int finalFd = fd;
    178     uint32_t finalOffset = offset;
    179     //If rotator is to be used, queue to it, so it can ROTATE.
    180     if(mRotUsed) {
    181         if(!mRot->queueBuffer(fd, offset)) {
    182             ALOGE("GenPipe Rotator play failed");
    183             return false;
    184         }
    185         //Configure MDP's source buffer as the current output buffer of rotator
    186         if(mRot->getDstMemId() != -1) {
    187             finalFd = mRot->getDstMemId();
    188             finalOffset = mRot->getDstOffset();
    189         } else {
    190             //Could be -1 for NullRotator, if queue above succeeds.
    191             //Need an actual rotator. Modify overlay State Traits.
    192             //Not fatal, keep queuing to MDP without rotation.
    193             ALOGE("Null rotator in use, where an actual is required");
    194         }
    195     }
    196     return mCtrlData.data.queueBuffer(finalFd, finalOffset);
    197 }
    198 
    199 int GenericPipe::getCtrlFd() const {
    200     return mCtrlData.ctrl.getFd();
    201 }
    202 
    203 utils::Dim GenericPipe::getCrop() const
    204 {
    205     return mCtrlData.ctrl.getCrop();
    206 }
    207 
    208 void GenericPipe::dump() const
    209 {
    210     ALOGE("== Dump Generic pipe start ==");
    211     ALOGE("pipe state = %d", (int)pipeState);
    212     OVASSERT(mRot, "GenericPipe should have a valid Rot");
    213     mCtrlData.ctrl.dump();
    214     mCtrlData.data.dump();
    215     mRot->dump();
    216     ALOGE("== Dump Generic pipe end ==");
    217 }
    218 
    219 void GenericPipe::getDump(char *buf, size_t len) {
    220     mCtrlData.ctrl.getDump(buf, len);
    221     mCtrlData.data.getDump(buf, len);
    222     if(mRotUsed && mRot)
    223         mRot->getDump(buf, len);
    224 }
    225 
    226 bool GenericPipe::isClosed() const  {
    227     return (pipeState == CLOSED);
    228 }
    229 
    230 bool GenericPipe::isOpen() const  {
    231     return (pipeState == OPEN);
    232 }
    233 
    234 bool GenericPipe::setClosed() {
    235     pipeState = CLOSED;
    236     return true;
    237 }
    238 
    239 
    240 } //namespace overlay
    241