• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 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 "overlay.h"
31 #include "overlayWriteback.h"
32 #include "mdpWrapper.h"
33 
34 namespace overlay {
35 
36 //=========== class WritebackMem ==============================================
manageMem(uint32_t size,bool isSecure)37 bool WritebackMem::manageMem(uint32_t size, bool isSecure) {
38     if(mBuf.bufSz() == size) {
39         return true;
40     }
41     if(mBuf.valid()) {
42         if(!mBuf.close()) {
43             ALOGE("%s error closing mem", __func__);
44             return false;
45         }
46     }
47     return alloc(size, isSecure);
48 }
49 
alloc(uint32_t size,bool isSecure)50 bool WritebackMem::alloc(uint32_t size, bool isSecure) {
51     if(!mBuf.open(NUM_BUFS, size, isSecure)){
52         ALOGE("%s: Failed to open", __func__);
53         mBuf.close();
54         return false;
55     }
56 
57     OVASSERT(MAP_FAILED != mBuf.addr(), "MAP failed");
58     OVASSERT(mBuf.getFD() != -1, "getFd is -1");
59 
60     mCurrOffsetIndex = 0;
61     for (uint32_t i = 0; i < NUM_BUFS; i++) {
62         mOffsets[i] = i * size;
63     }
64     return true;
65 }
66 
dealloc()67 bool WritebackMem::dealloc() {
68     bool ret = true;
69     if(mBuf.valid()) {
70         ret = mBuf.close();
71     }
72     return ret;
73 }
74 
75 //=========== class Writeback =================================================
Writeback()76 Writeback::Writeback() : mXres(0), mYres(0), mOpFmt(-1) {
77     int fbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
78     if(!utils::openDev(mFd, fbNum, Res::fbPath, O_RDWR)) {
79         ALOGE("%s failed to init %s", __func__, Res::fbPath);
80         return;
81     }
82     startSession();
83 }
84 
~Writeback()85 Writeback::~Writeback() {
86     stopSession();
87     if (!mFd.close()) {
88         ALOGE("%s error closing fd", __func__);
89     }
90 }
91 
startSession()92 bool Writeback::startSession() {
93     if(!mdp_wrapper::wbInitStart(mFd.getFD())) {
94         ALOGE("%s failed", __func__);
95         return false;
96     }
97     return true;
98 }
99 
stopSession()100 bool Writeback::stopSession() {
101     if(mFd.valid()) {
102         if(!mdp_wrapper::wbStopTerminate(mFd.getFD())) {
103             ALOGE("%s failed", __func__);
104             return false;
105         }
106     } else {
107         ALOGE("%s Invalid fd", __func__);
108         return false;
109     }
110     return true;
111 }
112 
configureDpyInfo(int xres,int yres)113 bool Writeback::configureDpyInfo(int xres, int yres) {
114     if(mXres != xres || mYres != yres) {
115         fb_var_screeninfo vinfo;
116         memset(&vinfo, 0, sizeof(fb_var_screeninfo));
117         if(!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) {
118             ALOGE("%s failed", __func__);
119             return false;
120         }
121         vinfo.xres = xres;
122         vinfo.yres = yres;
123         vinfo.xres_virtual = xres;
124         vinfo.yres_virtual = yres;
125         vinfo.xoffset = 0;
126         vinfo.yoffset = 0;
127         if(!mdp_wrapper::setVScreenInfo(mFd.getFD(), vinfo)) {
128             ALOGE("%s failed", __func__);
129             return false;
130         }
131         mXres = xres;
132         mYres = yres;
133     }
134     return true;
135 }
136 
configureMemory(uint32_t size,bool isSecure)137 bool Writeback::configureMemory(uint32_t size, bool isSecure) {
138     if(!mWbMem.manageMem(size, isSecure)) {
139         ALOGE("%s failed, memory failure", __func__);
140         return false;
141     }
142     return true;
143 }
144 
queueBuffer(int opFd,uint32_t opOffset)145 bool Writeback::queueBuffer(int opFd, uint32_t opOffset) {
146     memset(&mFbData, 0, sizeof(struct msmfb_data));
147     //Queue
148     mFbData.offset = opOffset;
149     mFbData.memory_id = opFd;
150     mFbData.id = 0;
151     mFbData.flags = 0;
152     if(!mdp_wrapper::wbQueueBuffer(mFd.getFD(), mFbData)) {
153         ALOGE("%s: queuebuffer failed", __func__);
154         return false;
155     }
156     return true;
157 }
158 
dequeueBuffer()159 bool Writeback::dequeueBuffer() {
160     //Dequeue
161     mFbData.flags = MSMFB_WRITEBACK_DEQUEUE_BLOCKING;
162     if(!mdp_wrapper::wbDequeueBuffer(mFd.getFD(), mFbData)) {
163         ALOGE("%s: dequeuebuffer failed", __func__);
164         return false;
165     }
166     return true;
167 }
168 
writeSync(int opFd,uint32_t opOffset)169 bool Writeback::writeSync(int opFd, uint32_t opOffset) {
170     if(!queueBuffer(opFd, opOffset)) {
171         return false;
172     }
173     if(!Overlay::displayCommit(mFd.getFD())) {
174         return false;
175     }
176     if(!dequeueBuffer()) {
177         return false;
178     }
179     return true;
180 }
181 
writeSync()182 bool Writeback::writeSync() {
183     mWbMem.useNextBuffer();
184     return writeSync(mWbMem.getDstFd(), mWbMem.getOffset());
185 }
186 
setOutputFormat(int mdpFormat)187 bool Writeback::setOutputFormat(int mdpFormat) {
188     if(mdpFormat != mOpFmt) {
189         struct msmfb_metadata metadata;
190         memset(&metadata, 0 , sizeof(metadata));
191         metadata.op = metadata_op_wb_format;
192         metadata.data.mixer_cfg.writeback_format = mdpFormat;
193         if (ioctl(mFd.getFD(), MSMFB_METADATA_SET, &metadata) < 0) {
194             ALOGE("Error setting MDP Writeback format");
195             return false;
196         }
197         mOpFmt = mdpFormat;
198     }
199     return true;
200 }
201 
getOutputFormat()202 int Writeback::getOutputFormat() {
203     if(mOpFmt < 0) {
204         struct msmfb_metadata metadata;
205         memset(&metadata, 0 , sizeof(metadata));
206         metadata.op = metadata_op_wb_format;
207         if (ioctl(mFd.getFD(), MSMFB_METADATA_GET, &metadata) < 0) {
208             ALOGE("Error retrieving MDP Writeback format");
209             return -1;
210         }
211         mOpFmt =  metadata.data.mixer_cfg.writeback_format;
212     }
213     return mOpFmt;
214 }
215 
216 //static
217 
getInstance()218 Writeback *Writeback::getInstance() {
219     if(sWb == NULL) {
220         sWb = new Writeback();
221     }
222     sUsed = true;
223     return sWb;
224 }
225 
configDone()226 void Writeback::configDone() {
227     if(sUsed == false && sWb) {
228         delete sWb;
229         sWb = NULL;
230     }
231 }
232 
clear()233 void Writeback::clear() {
234     sUsed = false;
235     if(sWb) {
236         delete sWb;
237         sWb = NULL;
238     }
239 }
240 
getDump(char * buf,size_t len)241 bool Writeback::getDump(char *buf, size_t len) {
242     if(sWb) {
243         utils::getDump(buf, len, "WBData", sWb->mFbData);
244         char str[4] = {'\0'};
245         snprintf(str, 4, "\n");
246         strncat(buf, str, strlen(str));
247         return true;
248     }
249     return false;
250 }
251 
252 Writeback *Writeback::sWb = 0;
253 bool Writeback::sUsed = false;
254 
255 } //namespace overlay
256