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