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 namespace overlay {
     35 
     36 //=========== class WritebackMem ==============================================
     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 
     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 
     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 =================================================
     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 
     85 Writeback::~Writeback() {
     86     stopSession();
     87     if (!mFd.close()) {
     88         ALOGE("%s error closing fd", __func__);
     89     }
     90 }
     91 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    182 bool Writeback::writeSync() {
    183     mWbMem.useNextBuffer();
    184     return writeSync(mWbMem.getDstFd(), mWbMem.getOffset());
    185 }
    186 
    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 
    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 
    218 Writeback *Writeback::getInstance() {
    219     if(sWb == NULL) {
    220         sWb = new Writeback();
    221     }
    222     sUsed = true;
    223     return sWb;
    224 }
    225 
    226 void Writeback::configDone() {
    227     if(sUsed == false && sWb) {
    228         delete sWb;
    229         sWb = NULL;
    230     }
    231 }
    232 
    233 void Writeback::clear() {
    234     sUsed = false;
    235     if(sWb) {
    236         delete sWb;
    237         sWb = NULL;
    238     }
    239 }
    240 
    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