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 34namespace overlay { 35 36//=========== class WritebackMem ============================================== 37bool 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 50bool 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 67bool WritebackMem::dealloc() { 68 bool ret = true; 69 if(mBuf.valid()) { 70 ret = mBuf.close(); 71 } 72 return ret; 73} 74 75//=========== class Writeback ================================================= 76Writeback::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 85Writeback::~Writeback() { 86 stopSession(); 87 if (!mFd.close()) { 88 ALOGE("%s error closing fd", __func__); 89 } 90} 91 92bool Writeback::startSession() { 93 if(!mdp_wrapper::wbInitStart(mFd.getFD())) { 94 ALOGE("%s failed", __func__); 95 return false; 96 } 97 return true; 98} 99 100bool 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 113bool 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 137bool 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 145bool 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 159bool 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 169bool 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 182bool Writeback::writeSync() { 183 mWbMem.useNextBuffer(); 184 return writeSync(mWbMem.getDstFd(), mWbMem.getOffset()); 185} 186 187bool 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 202int 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 218Writeback *Writeback::getInstance() { 219 if(sWb == NULL) { 220 sWb = new Writeback(); 221 } 222 sUsed = true; 223 return sWb; 224} 225 226void Writeback::configDone() { 227 if(sUsed == false && sWb) { 228 delete sWb; 229 sWb = NULL; 230 } 231} 232 233void Writeback::clear() { 234 sUsed = false; 235 if(sWb) { 236 delete sWb; 237 sWb = NULL; 238 } 239} 240 241bool 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 252Writeback *Writeback::sWb = 0; 253bool Writeback::sUsed = false; 254 255} //namespace overlay 256