overlayRotator.cpp revision ee7fc0347e52276d43413e91f31d72d6db99dcfb
1/*
2* Copyright (C) 2008 The Android Open Source Project
3* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
4*
5* Licensed under the Apache License, Version 2.0 (the "License");
6* you may not use this file except in compliance with the License.
7* You may obtain a copy of the License at
8*
9*      http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing, software
12* distributed under the License is distributed on an "AS IS" BASIS,
13* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14* See the License for the specific language governing permissions and
15* limitations under the License.
16*/
17
18#include "overlayRotator.h"
19#include "overlayUtils.h"
20
21namespace ovutils = overlay::utils;
22
23namespace overlay {
24
25int IRotatorHw::getRotatorHwType() {
26    //TODO figure out based on ioctl
27    return TYPE_MDP;
28}
29
30bool RotMem::close() {
31    bool ret = true;
32    for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) {
33        // skip current, and if valid, close
34        if(m[i].valid()) {
35            if(m[i].close() == false) {
36                ALOGE("%s error in closing rot mem %d", __FUNCTION__, i);
37                ret = false;
38            }
39        }
40    }
41    return ret;
42}
43
44bool MdpRot::init()
45{
46    if(!mFd.open(Res::rotPath, O_RDWR)){
47        ALOGE("MdpRot failed to init %s", Res::rotPath);
48        return false;
49    }
50    return true;
51}
52
53void MdpRot::setSource(const overlay::utils::Whf& awhf) {
54    utils::Whf whf(awhf);
55
56    mRotImgInfo.src.format = whf.format;
57    if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
58        whf.format == MDP_Y_CBCR_H2V2_TILE) {
59        whf.w =  utils::alignup(awhf.w, 64);
60        whf.h = utils::alignup(awhf.h, 32);
61    }
62
63    mRotImgInfo.src.width = whf.w;
64    mRotImgInfo.src.height = whf.h;
65
66    mRotImgInfo.src_rect.w = whf.w;
67    mRotImgInfo.src_rect.h = whf.h;
68
69    mRotImgInfo.dst.width = whf.w;
70    mRotImgInfo.dst.height = whf.h;
71
72    mBufSize = awhf.size;
73}
74
75void MdpRot::setFlags(const utils::eMdpFlags& flags) {
76    mRotImgInfo.secure = 0;
77    if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
78        mRotImgInfo.secure = 1;
79}
80
81void MdpRot::setTransform(const utils::eTransform& rot, const bool& rotUsed)
82{
83    mOrientation = rot;
84    int r = utils::getMdpOrient(rot);
85    ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r);
86    setRotations(r);
87    setDisable();
88    if(rotUsed) {
89        setEnable();
90    }
91}
92
93void MdpRot::doTransform() {
94    switch(mOrientation) {
95        case utils::OVERLAY_TRANSFORM_ROT_90:
96        case utils::OVERLAY_TRANSFORM_ROT_90_FLIP_H:
97        case utils::OVERLAY_TRANSFORM_ROT_90_FLIP_V:
98        case utils::OVERLAY_TRANSFORM_ROT_270:
99            utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height);
100            break;
101        default:
102            break;
103    }
104}
105
106bool MdpRot::commit() {
107    doTransform();
108    if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) {
109        ALOGE("MdpRot commit failed");
110        dump();
111        return false;
112    }
113    mRotDataInfo.session_id = mRotImgInfo.session_id;
114    return true;
115}
116
117bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz)
118{
119    OvMem mem;
120
121    OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
122
123    if(!mem.open(numbufs, bufsz, mRotImgInfo.secure)){
124        ALOGE("%s: Failed to open", __func__);
125        mem.close();
126        return false;
127    }
128
129    OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
130    OVASSERT(mem.getFD() != -1, "getFd is -1");
131
132    mRotDataInfo.dst.memory_id = mem.getFD();
133    mRotDataInfo.dst.offset = 0;
134    mMem.curr().m = mem;
135    return true;
136}
137
138bool MdpRot::close() {
139    bool success = true;
140    if(mFd.valid() && (getSessId() > 0)) {
141        if(!mdp_wrapper::endRotator(mFd.getFD(), getSessId())) {
142            ALOGE("Mdp Rot error endRotator, fd=%d sessId=%d",
143                    mFd.getFD(), getSessId());
144            success = false;
145        }
146    }
147    if (!mFd.close()) {
148        ALOGE("Mdp Rot error closing fd");
149        success = false;
150    }
151    if (!mMem.close()) {
152        ALOGE("Mdp Rot error closing mem");
153        success = false;
154    }
155    reset();
156    return success;
157}
158
159bool MdpRot::remap(uint32_t numbufs) {
160    // if current size changed, remap
161    if(mBufSize == mMem.curr().size()) {
162        ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, mBufSize);
163        return true;
164    }
165
166    ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
167    OVASSERT(!mMem.prev().valid(), "Prev should not be valid");
168
169    // ++mMem will make curr to be prev, and prev will be curr
170    ++mMem;
171    if(!open_i(numbufs, mBufSize)) {
172        ALOGE("%s Error could not open", __FUNCTION__);
173        return false;
174    }
175    for (uint32_t i = 0; i < numbufs; ++i) {
176        mMem.curr().mRotOffset[i] = i * mBufSize;
177    }
178    return true;
179}
180
181void MdpRot::reset() {
182    ovutils::memset0(mRotImgInfo);
183    ovutils::memset0(mRotDataInfo);
184    ovutils::memset0(mMem.curr().mRotOffset);
185    ovutils::memset0(mMem.prev().mRotOffset);
186    mMem.curr().mCurrOffset = 0;
187    mMem.prev().mCurrOffset = 0;
188    mBufSize = 0;
189    mOrientation = utils::OVERLAY_TRANSFORM_0;
190}
191
192bool MdpRot::queueBuffer(int fd, uint32_t offset) {
193    if(enabled()) {
194        mRotDataInfo.src.memory_id = fd;
195        mRotDataInfo.src.offset = offset;
196
197        remap(RotMem::Mem::ROT_NUM_BUFS);
198        OVASSERT(mMem.curr().m.numBufs(),
199                "queueBuffer numbufs is 0");
200        mRotDataInfo.dst.offset =
201                mMem.curr().mRotOffset[mMem.curr().mCurrOffset];
202        mMem.curr().mCurrOffset =
203                (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs();
204
205        if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) {
206            ALOGE("MdpRot failed rotate");
207            dump();
208            return false;
209        }
210
211        // if the prev mem is valid, we need to close
212        if(mMem.prev().valid()) {
213            // FIXME if no wait for vsync the above
214            // play will return immediatly and might cause
215            // tearing when prev.close is called.
216            if(!mMem.prev().close()) {
217                ALOGE("%s error in closing prev rot mem", __FUNCTION__);
218                return false;
219            }
220        }
221    }
222    return true;
223}
224
225void MdpRot::dump() const {
226    ALOGE("== Dump MdpRot start ==");
227    mFd.dump();
228    mMem.curr().m.dump();
229    mdp_wrapper::dump("mRotImgInfo", mRotImgInfo);
230    mdp_wrapper::dump("mRotDataInfo", mRotDataInfo);
231    ALOGE("== Dump MdpRot end ==");
232}
233}
234