overlayRotator.cpp revision 103c736926cace1ff5a6d154715b375ff1018f8e
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright (c) 2010-2012, 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 "overlayRotator.h"
21#include "overlayUtils.h"
22#include "mdp_version.h"
23#include "gr.h"
24
25namespace ovutils = overlay::utils;
26
27namespace overlay {
28
29//============Rotator=========================
30
31Rotator::~Rotator() {}
32
33Rotator* Rotator::getRotator() {
34    int type = getRotatorHwType();
35    if(type == TYPE_MDP) {
36        return new MdpRot(); //will do reset
37    } else if(type == TYPE_MDSS) {
38        return new MdssRot();
39    } else {
40        ALOGE("%s Unknown h/w type %d", __FUNCTION__, type);
41        return NULL;
42    }
43}
44
45uint32_t Rotator::calcOutputBufSize(const utils::Whf& destWhf) {
46    //dummy aligned w & h.
47    int alW = 0, alH = 0;
48    int halFormat = ovutils::getHALFormat(destWhf.format);
49    //A call into gralloc/memalloc
50    return getBufferSizeAndDimensions(
51            destWhf.w, destWhf.h, halFormat, alW, alH);
52}
53
54int Rotator::getRotatorHwType() {
55    int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
56    if (mdpVersion == qdutils::MDSS_V5)
57        return TYPE_MDSS;
58    return TYPE_MDP;
59}
60
61
62//============RotMem=========================
63
64bool RotMem::close() {
65    bool ret = true;
66    for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) {
67        // skip current, and if valid, close
68        if(m[i].valid()) {
69            if(m[i].close() == false) {
70                ALOGE("%s error in closing rot mem %d", __FUNCTION__, i);
71                ret = false;
72            }
73        }
74    }
75    return ret;
76}
77
78RotMem::Mem::Mem() : mCurrOffset(0) {
79    utils::memset0(mRotOffset);
80    for(int i = 0; i < ROT_NUM_BUFS; i++) {
81        mRelFence[i] = -1;
82    }
83}
84
85RotMem::Mem::~Mem() {
86    for(int i = 0; i < ROT_NUM_BUFS; i++) {
87        ::close(mRelFence[i]);
88        mRelFence[i] = -1;
89    }
90}
91
92void RotMem::Mem::setReleaseFd(const int& fence) {
93    int ret = 0;
94
95    if(mRelFence[mCurrOffset] >= 0) {
96        //Wait for previous usage of this buffer to be over.
97        //Can happen if rotation takes > vsync and a fast producer. i.e queue
98        //happens in subsequent vsyncs either because content is 60fps or
99        //because the producer is hasty sometimes.
100        ret = sync_wait(mRelFence[mCurrOffset], 1000);
101        if(ret < 0) {
102            ALOGE("%s: sync_wait error!! error no = %d err str = %s",
103                __FUNCTION__, errno, strerror(errno));
104        }
105        ::close(mRelFence[mCurrOffset]);
106    }
107    mRelFence[mCurrOffset] = fence;
108}
109
110//============RotMgr=========================
111
112RotMgr::RotMgr() {
113    for(int i = 0; i < MAX_ROT_SESS; i++) {
114        mRot[i] = 0;
115    }
116    mUseCount = 0;
117    mRotDevFd = -1;
118}
119
120RotMgr::~RotMgr() {
121    clear();
122}
123
124void RotMgr::configBegin() {
125    //Reset the number of objects used
126    mUseCount = 0;
127}
128
129void RotMgr::configDone() {
130    //Remove the top most unused objects. Videos come and go.
131    for(int i = mUseCount; i < MAX_ROT_SESS; i++) {
132        if(mRot[i]) {
133            delete mRot[i];
134            mRot[i] = 0;
135        }
136    }
137}
138
139Rotator* RotMgr::getNext() {
140    //Return a rot object, creating one if necessary
141    overlay::Rotator *rot = NULL;
142    if(mUseCount >= MAX_ROT_SESS) {
143        ALOGE("%s, MAX rotator sessions reached", __func__);
144    } else {
145        if(mRot[mUseCount] == NULL)
146            mRot[mUseCount] = overlay::Rotator::getRotator();
147        rot = mRot[mUseCount++];
148    }
149    return rot;
150}
151
152void RotMgr::clear() {
153    //Brute force obj destruction, helpful in suspend.
154    for(int i = 0; i < MAX_ROT_SESS; i++) {
155        if(mRot[i]) {
156            delete mRot[i];
157            mRot[i] = 0;
158        }
159    }
160    mUseCount = 0;
161    ::close(mRotDevFd);
162    mRotDevFd = -1;
163}
164
165void RotMgr::getDump(char *buf, size_t len) {
166    for(int i = 0; i < MAX_ROT_SESS; i++) {
167        if(mRot[i]) {
168            mRot[i]->getDump(buf, len);
169        }
170    }
171    char str[4] = {'\0'};
172    snprintf(str, 4, "\n");
173    strncat(buf, str, strlen(str));
174}
175
176int RotMgr::getRotDevFd() {
177    if(mRotDevFd < 0 && Rotator::getRotatorHwType() == Rotator::TYPE_MDSS) {
178        mRotDevFd = ::open("/dev/graphics/fb0", O_RDWR, 0);
179        if(mRotDevFd < 0) {
180            ALOGE("%s failed to open fb0", __FUNCTION__);
181        }
182    }
183    return mRotDevFd;
184}
185
186}
187