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 
MdpRot()28 MdpRot::MdpRot() {
29     reset();
30     init();
31 }
32 
~MdpRot()33 MdpRot::~MdpRot() { close(); }
34 
enabled() const35 bool MdpRot::enabled() const { return mRotImgInfo.enable; }
36 
setRotations(uint32_t r)37 void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = (uint8_t)r; }
38 
getDstMemId() const39 int MdpRot::getDstMemId() const {
40     return mRotDataInfo.dst.memory_id;
41 }
42 
getDstOffset() const43 uint32_t MdpRot::getDstOffset() const {
44     return mRotDataInfo.dst.offset;
45 }
46 
getDstFormat() const47 uint32_t MdpRot::getDstFormat() const {
48     return mRotImgInfo.dst.format;
49 }
50 
51 //Added for completeness. Not expected to be called.
getDstWhf() const52 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.
getDstDimensions() const61 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 
getSessId() const69 uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; }
70 
setDownscale(int ds)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 
save()80 void MdpRot::save() {
81     mLSRotImgInfo = mRotImgInfo;
82 }
83 
rotConfChanged() const84 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 
init()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 
setSource(const overlay::utils::Whf & awhf)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 
setCrop(const utils::Dim &)116 void MdpRot::setCrop(const utils::Dim& /*crop*/) {
117     // NO-OP for non-mdss rotator due to possible h/w limitations
118 }
119 
setFlags(const utils::eMdpFlags & flags)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 
setTransform(const utils::eTransform & rot)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 
doTransform()134 void MdpRot::doTransform() {
135     if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90)
136         utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height);
137 }
138 
commit()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 
calcOutputBufSize()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 
open_i(uint32_t numbufs,uint32_t bufsz)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 
close()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 
remap(uint32_t numbufs)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 
reset()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 
queueBuffer(int fd,uint32_t offset)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 
dump() const263 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 
getDump(char * buf,size_t len) const272 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