overlayGenPipe.cpp revision e2b94da0a7de2a5cad9ecb90ed3eee5dca219863
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
34namespace overlay {
35
36GenericPipe::GenericPipe(int dpy) : mFbNum(dpy), mRot(0), mRotUsed(false),
37        mRotDownscaleOpt(false), mPreRotated(false), pipeState(CLOSED) {
38    init();
39}
40
41GenericPipe::~GenericPipe() {
42    close();
43}
44
45bool 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
72bool 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
91void 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
102void GenericPipe::setCrop(const overlay::utils::Dim& d) {
103    mCtrlData.ctrl.setCrop(d);
104}
105
106void 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
114void GenericPipe::setPosition(const utils::Dim& d) {
115    mCtrlData.ctrl.setPosition(d);
116}
117
118bool GenericPipe::setVisualParams(const MetaData_t &metadata)
119{
120        return mCtrlData.ctrl.setVisualParams(metadata);
121}
122
123bool 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
169bool 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
199int GenericPipe::getCtrlFd() const {
200    return mCtrlData.ctrl.getFd();
201}
202
203utils::Dim GenericPipe::getCrop() const
204{
205    return mCtrlData.ctrl.getCrop();
206}
207
208void 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
219void 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
226bool GenericPipe::isClosed() const  {
227    return (pipeState == CLOSED);
228}
229
230bool GenericPipe::isOpen() const  {
231    return (pipeState == OPEN);
232}
233
234bool GenericPipe::setClosed() {
235    pipeState = CLOSED;
236    return true;
237}
238
239
240} //namespace overlay
241