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