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 
GenericPipe(int dpy)36 GenericPipe::GenericPipe(int dpy) : mFbNum(dpy), mRot(0), mRotUsed(false),
37         mRotDownscaleOpt(false), mPreRotated(false), pipeState(CLOSED) {
38     init();
39 }
40 
~GenericPipe()41 GenericPipe::~GenericPipe() {
42     close();
43 }
44 
init()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 
close()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 
setSource(const utils::PipeArgs & args)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 
setCrop(const overlay::utils::Dim & d)102 void GenericPipe::setCrop(const overlay::utils::Dim& d) {
103     mCtrlData.ctrl.setCrop(d);
104 }
105 
setTransform(const utils::eTransform & orient)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 
setPosition(const utils::Dim & d)114 void GenericPipe::setPosition(const utils::Dim& d) {
115     mCtrlData.ctrl.setPosition(d);
116 }
117 
setVisualParams(const MetaData_t & metadata)118 bool GenericPipe::setVisualParams(const MetaData_t &metadata)
119 {
120         return mCtrlData.ctrl.setVisualParams(metadata);
121 }
122 
commit()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 
queueBuffer(int fd,uint32_t offset)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 
getCtrlFd() const199 int GenericPipe::getCtrlFd() const {
200     return mCtrlData.ctrl.getFd();
201 }
202 
getCrop() const203 utils::Dim GenericPipe::getCrop() const
204 {
205     return mCtrlData.ctrl.getCrop();
206 }
207 
dump() const208 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 
getDump(char * buf,size_t len)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 
isClosed() const226 bool GenericPipe::isClosed() const  {
227     return (pipeState == CLOSED);
228 }
229 
isOpen() const230 bool GenericPipe::isOpen() const  {
231     return (pipeState == OPEN);
232 }
233 
setClosed()234 bool GenericPipe::setClosed() {
235     pipeState = CLOSED;
236     return true;
237 }
238 
239 
240 } //namespace overlay
241