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(!mdp_wrapper::wbStopTerminate(mFd.getFD())) {
    105             ALOGE("%s failed", __func__);
    106             return false;
    107         }
    108     } else {
    109         ALOGE("%s Invalid fd", __func__);
    110         return false;
    111     }
    112     return true;
    113 }
    114 
    115 bool Writeback::configureDpyInfo(int xres, int yres) {
    116     if(mXres != xres || mYres != yres) {
    117         fb_var_screeninfo vinfo;
    118         memset(&vinfo, 0, sizeof(fb_var_screeninfo));
    119         if(!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) {
    120             ALOGE("%s failed", __func__);
    121             return false;
    122         }
    123         vinfo.xres = xres;
    124         vinfo.yres = yres;
    125         vinfo.xres_virtual = xres;
    126         vinfo.yres_virtual = yres;
    127         vinfo.xoffset = 0;
    128         vinfo.yoffset = 0;
    129         if(!mdp_wrapper::setVScreenInfo(mFd.getFD(), vinfo)) {
    130             ALOGE("%s failed", __func__);
    131             return false;
    132         }
    133         mXres = xres;
    134         mYres = yres;
    135     }
    136     return true;
    137 }
    138 
    139 bool Writeback::configureMemory(uint32_t size) {
    140     if(!mWbMem.manageMem(size, mSecure)) {
    141         ALOGE("%s failed, memory failure", __func__);
    142         return false;
    143     }
    144     return true;
    145 }
    146 
    147 bool Writeback::queueBuffer(int opFd, uint32_t opOffset) {
    148     memset(&mFbData, 0, sizeof(struct msmfb_data));
    149     //Queue
    150     mFbData.offset = opOffset;
    151     mFbData.memory_id = opFd;
    152     mFbData.id = 0;
    153     mFbData.flags = 0;
    154     if(!mdp_wrapper::wbQueueBuffer(mFd.getFD(), mFbData)) {
    155         ALOGE("%s: queuebuffer failed", __func__);
    156         return false;
    157     }
    158     return true;
    159 }
    160 
    161 bool Writeback::dequeueBuffer() {
    162     //Dequeue
    163     mFbData.flags = MSMFB_WRITEBACK_DEQUEUE_BLOCKING;
    164     if(!mdp_wrapper::wbDequeueBuffer(mFd.getFD(), mFbData)) {
    165         ALOGE("%s: dequeuebuffer failed", __func__);
    166         return false;
    167     }
    168     return true;
    169 }
    170 
    171 bool Writeback::writeSync(int opFd, uint32_t opOffset) {
    172     if(!queueBuffer(opFd, opOffset)) {
    173         return false;
    174     }
    175     if(!Overlay::displayCommit(mFd.getFD())) {
    176         return false;
    177     }
    178     if(!dequeueBuffer()) {
    179         return false;
    180     }
    181     return true;
    182 }
    183 
    184 bool Writeback::writeSync() {
    185     mWbMem.useNextBuffer();
    186     return writeSync(mWbMem.getDstFd(), mWbMem.getOffset());
    187 }
    188 
    189 bool Writeback::setOutputFormat(int mdpFormat) {
    190     if(mdpFormat != mOpFmt) {
    191         struct msmfb_metadata metadata;
    192         memset(&metadata, 0 , sizeof(metadata));
    193         metadata.op = metadata_op_wb_format;
    194         metadata.data.mixer_cfg.writeback_format = mdpFormat;
    195         if (ioctl(mFd.getFD(), MSMFB_METADATA_SET, &metadata) < 0) {
    196             ALOGE("Error setting MDP Writeback format");
    197             return false;
    198         }
    199         mOpFmt = mdpFormat;
    200     }
    201     return true;
    202 }
    203 
    204 int Writeback::getOutputFormat() {
    205     if(mOpFmt < 0) {
    206         struct msmfb_metadata metadata;
    207         memset(&metadata, 0 , sizeof(metadata));
    208         metadata.op = metadata_op_wb_format;
    209         if (ioctl(mFd.getFD(), MSMFB_METADATA_GET, &metadata) < 0) {
    210             ALOGE("Error retrieving MDP Writeback format");
    211             return -1;
    212         }
    213         mOpFmt =  metadata.data.mixer_cfg.writeback_format;
    214     }
    215     return mOpFmt;
    216 }
    217 
    218 bool Writeback::setSecure(bool isSecure) {
    219     if(isSecure != mSecure) {
    220         // Call IOCTL to set WB interface as secure
    221         struct msmfb_metadata metadata;
    222         memset(&metadata, 0 , sizeof(metadata));
    223         metadata.op = metadata_op_wb_secure;
    224         metadata.data.secure_en = isSecure;
    225         if (ioctl(mFd.getFD(), MSMFB_METADATA_SET, &metadata) < 0) {
    226             ALOGE("Error setting MDP WB secure");
    227             return false;
    228         }
    229         mSecure = isSecure;
    230     }
    231     return true;
    232 }
    233 
    234 //static
    235 
    236 Writeback *Writeback::getInstance() {
    237     if(sWb == NULL) {
    238         sWb = new Writeback();
    239     }
    240     sUsed = true;
    241     return sWb;
    242 }
    243 
    244 void Writeback::configDone() {
    245     if(sUsed == false && sWb) {
    246         delete sWb;
    247         sWb = NULL;
    248     }
    249 }
    250 
    251 void Writeback::clear() {
    252     sUsed = false;
    253     if(sWb) {
    254         delete sWb;
    255         sWb = NULL;
    256     }
    257 }
    258 
    259 bool Writeback::getDump(char *buf, size_t len) {
    260     if(sWb) {
    261         utils::getDump(buf, len, "WBData", sWb->mFbData);
    262         char str[4] = {'\0'};
    263         snprintf(str, 4, "\n");
    264         strlcat(buf, str, len);
    265         return true;
    266     }
    267     return false;
    268 }
    269 
    270 Writeback *Writeback::sWb = 0;
    271 bool Writeback::sUsed = false;
    272 
    273 } //namespace overlay
    274