Home | History | Annotate | Download | only in liboverlay
      1 /*
      2 * Copyright (c) 2011-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 "pipes/overlayGenPipe.h"
     32 #include "mdp_version.h"
     33 #include "qdMetaData.h"
     34 
     35 #define PIPE_DEBUG 0
     36 
     37 namespace overlay {
     38 using namespace utils;
     39 
     40 Overlay::Overlay() {
     41     PipeBook::NUM_PIPES = qdutils::MDPVersion::getInstance().getTotalPipes();
     42     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
     43         mPipeBook[i].init();
     44     }
     45 
     46     mDumpStr[0] = '\0';
     47 }
     48 
     49 Overlay::~Overlay() {
     50     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
     51         mPipeBook[i].destroy();
     52     }
     53 }
     54 
     55 void Overlay::configBegin() {
     56     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
     57         //Mark as available for this round.
     58         PipeBook::resetUse(i);
     59         PipeBook::resetAllocation(i);
     60     }
     61     sForceSetBitmap = 0;
     62     mDumpStr[0] = '\0';
     63 }
     64 
     65 void Overlay::configDone() {
     66     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
     67         if(PipeBook::isNotUsed(i)) {
     68             //Forces UNSET on pipes, flushes rotator memory and session, closes
     69             //fds
     70             if(mPipeBook[i].valid()) {
     71                 char str[32];
     72                 sprintf(str, "Unset=%s dpy=%d mix=%d; ",
     73                         PipeBook::getDestStr((eDest)i),
     74                         mPipeBook[i].mDisplay, mPipeBook[i].mMixer);
     75 #if PIPE_DEBUG
     76                 strncat(mDumpStr, str, strlen(str));
     77 #endif
     78             }
     79             mPipeBook[i].destroy();
     80         }
     81     }
     82     dump();
     83     PipeBook::save();
     84 }
     85 
     86 eDest Overlay::nextPipe(eMdpPipeType type, int dpy, int mixer) {
     87     eDest dest = OV_INVALID;
     88 
     89     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
     90         if( (type == OV_MDP_PIPE_ANY || //Pipe type match
     91              type == PipeBook::getPipeType((eDest)i)) &&
     92             (mPipeBook[i].mDisplay == DPY_UNUSED || //Free or same display
     93              mPipeBook[i].mDisplay == dpy) &&
     94             (mPipeBook[i].mMixer == MIXER_UNUSED || //Free or same mixer
     95              mPipeBook[i].mMixer == mixer) &&
     96             PipeBook::isNotAllocated(i) && //Free pipe
     97             !(sDMAMode == DMA_BLOCK_MODE && //DMA pipe in Line mode
     98                PipeBook::getPipeType((eDest)i) == OV_MDP_PIPE_DMA)) {
     99             dest = (eDest)i;
    100             PipeBook::setAllocation(i);
    101             break;
    102         }
    103     }
    104 
    105     if(dest != OV_INVALID) {
    106         int index = (int)dest;
    107         mPipeBook[index].mDisplay = dpy;
    108         mPipeBook[index].mMixer = mixer;
    109         if(not mPipeBook[index].valid()) {
    110             mPipeBook[index].mPipe = new GenericPipe(dpy);
    111             char str[32];
    112             snprintf(str, 32, "Set=%s dpy=%d mix=%d; ",
    113                      PipeBook::getDestStr(dest), dpy, mixer);
    114 #if PIPE_DEBUG
    115             strncat(mDumpStr, str, strlen(str));
    116 #endif
    117         }
    118     } else {
    119         ALOGD_IF(PIPE_DEBUG, "Pipe unavailable type=%d display=%d mixer=%d",
    120                 (int)type, dpy, mixer);
    121     }
    122 
    123     return dest;
    124 }
    125 
    126 bool Overlay::isPipeTypeAttached(eMdpPipeType type) {
    127     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
    128         if(type == PipeBook::getPipeType((eDest)i) &&
    129                 mPipeBook[i].mDisplay != DPY_UNUSED) {
    130             return true;
    131         }
    132     }
    133     return false;
    134 }
    135 
    136 bool Overlay::commit(utils::eDest dest) {
    137     bool ret = false;
    138     int index = (int)dest;
    139     validate(index);
    140 
    141     if(mPipeBook[index].mPipe->commit()) {
    142         ret = true;
    143         PipeBook::setUse((int)dest);
    144         if(sForceSetBitmap & (1 << mPipeBook[index].mDisplay)) {
    145             mPipeBook[index].mPipe->forceSet();
    146         }
    147     } else {
    148         int dpy = mPipeBook[index].mDisplay;
    149         for(int i = 0; i < PipeBook::NUM_PIPES; i++)
    150             if (mPipeBook[i].mDisplay == dpy) {
    151                 PipeBook::resetAllocation(i);
    152                 PipeBook::resetUse(i);
    153                 if(mPipeBook[i].valid()) {
    154                     mPipeBook[i].mPipe->forceSet();
    155                 }
    156             }
    157     }
    158     return ret;
    159 }
    160 
    161 bool Overlay::queueBuffer(int fd, uint32_t offset,
    162         utils::eDest dest) {
    163     int index = (int)dest;
    164     bool ret = false;
    165     validate(index);
    166     //Queue only if commit() has succeeded (and the bit set)
    167     if(PipeBook::isUsed((int)dest)) {
    168         ret = mPipeBook[index].mPipe->queueBuffer(fd, offset);
    169     }
    170     return ret;
    171 }
    172 
    173 void Overlay::setCrop(const utils::Dim& d,
    174         utils::eDest dest) {
    175     int index = (int)dest;
    176     validate(index);
    177     mPipeBook[index].mPipe->setCrop(d);
    178 }
    179 
    180 void Overlay::setPosition(const utils::Dim& d,
    181         utils::eDest dest) {
    182     int index = (int)dest;
    183     validate(index);
    184     mPipeBook[index].mPipe->setPosition(d);
    185 }
    186 
    187 void Overlay::setTransform(const int orient,
    188         utils::eDest dest) {
    189     int index = (int)dest;
    190     validate(index);
    191 
    192     utils::eTransform transform =
    193             static_cast<utils::eTransform>(orient);
    194     mPipeBook[index].mPipe->setTransform(transform);
    195 
    196 }
    197 
    198 void Overlay::setSource(const utils::PipeArgs args,
    199         utils::eDest dest) {
    200     int index = (int)dest;
    201     validate(index);
    202 
    203     PipeArgs newArgs(args);
    204     if(PipeBook::getPipeType(dest) == OV_MDP_PIPE_VG) {
    205         setMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_SHARE);
    206     } else {
    207         clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_SHARE);
    208     }
    209 
    210     if(PipeBook::getPipeType(dest) == OV_MDP_PIPE_DMA) {
    211         setMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA);
    212     } else {
    213         clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA);
    214     }
    215 
    216     mPipeBook[index].mPipe->setSource(newArgs);
    217 }
    218 
    219 void Overlay::setVisualParams(const MetaData_t& metadata, utils::eDest dest) {
    220     int index = (int)dest;
    221     validate(index);
    222     mPipeBook[index].mPipe->setVisualParams(metadata);
    223 }
    224 
    225 Overlay* Overlay::getInstance() {
    226     if(sInstance == NULL) {
    227         sInstance = new Overlay();
    228     }
    229     return sInstance;
    230 }
    231 
    232 // Clears any VG pipes allocated to the fb devices
    233 // Generates a LUT for pipe types.
    234 int Overlay::initOverlay() {
    235     int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
    236     int numPipesXType[OV_MDP_PIPE_ANY] = {0};
    237     numPipesXType[OV_MDP_PIPE_RGB] =
    238             qdutils::MDPVersion::getInstance().getRGBPipes();
    239     numPipesXType[OV_MDP_PIPE_VG] =
    240             qdutils::MDPVersion::getInstance().getVGPipes();
    241     numPipesXType[OV_MDP_PIPE_DMA] =
    242             qdutils::MDPVersion::getInstance().getDMAPipes();
    243 
    244     int index = 0;
    245     for(int X = 0; X < (int)OV_MDP_PIPE_ANY; X++) { //iterate over types
    246         for(int j = 0; j < numPipesXType[X]; j++) { //iterate over num
    247             PipeBook::pipeTypeLUT[index] = (utils::eMdpPipeType)X;
    248             index++;
    249         }
    250     }
    251 
    252     if (mdpVersion < qdutils::MDSS_V5 && mdpVersion != qdutils::MDP_V3_0_4) {
    253         msmfb_mixer_info_req  req;
    254         mdp_mixer_info *minfo = NULL;
    255         char name[64];
    256         int fd = -1;
    257         for(int i = 0; i < MAX_FB_DEVICES; i++) {
    258             snprintf(name, 64, FB_DEVICE_TEMPLATE, i);
    259             ALOGD("initoverlay:: opening the device:: %s", name);
    260             fd = ::open(name, O_RDWR, 0);
    261             if(fd < 0) {
    262                 ALOGE("cannot open framebuffer(%d)", i);
    263                 return -1;
    264             }
    265             //Get the mixer configuration */
    266             req.mixer_num = i;
    267             if (ioctl(fd, MSMFB_MIXER_INFO, &req) == -1) {
    268                 ALOGE("ERROR: MSMFB_MIXER_INFO ioctl failed");
    269                 close(fd);
    270                 return -1;
    271             }
    272             minfo = req.info;
    273             for (int j = 0; j < req.cnt; j++) {
    274                 ALOGD("ndx=%d num=%d z_order=%d", minfo->pndx, minfo->pnum,
    275                       minfo->z_order);
    276                 // clear any pipe connected to mixer including base pipe.
    277                 int index = minfo->pndx;
    278                 ALOGD("Unset overlay with index: %d at mixer %d", index, i);
    279                 if(ioctl(fd, MSMFB_OVERLAY_UNSET, &index) == -1) {
    280                     ALOGE("ERROR: MSMFB_OVERLAY_UNSET failed");
    281                     close(fd);
    282                     return -1;
    283                 }
    284                 minfo++;
    285             }
    286             close(fd);
    287             fd = -1;
    288         }
    289     }
    290 
    291     FILE *displayDeviceFP = NULL;
    292     const int MAX_FRAME_BUFFER_NAME_SIZE = 128;
    293     char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
    294     char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
    295     const char *strDtvPanel = "dtv panel";
    296     const char *strWbPanel = "writeback panel";
    297 
    298     for(int num = 1; num < MAX_FB_DEVICES; num++) {
    299         snprintf (msmFbTypePath, sizeof(msmFbTypePath),
    300                 "/sys/class/graphics/fb%d/msm_fb_type", num);
    301         displayDeviceFP = fopen(msmFbTypePath, "r");
    302 
    303         if(displayDeviceFP){
    304             fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
    305                     displayDeviceFP);
    306 
    307             if(strncmp(fbType, strDtvPanel, strlen(strDtvPanel)) == 0) {
    308                 sDpyFbMap[DPY_EXTERNAL] = num;
    309             } else if(strncmp(fbType, strWbPanel, strlen(strWbPanel)) == 0) {
    310                 sDpyFbMap[DPY_WRITEBACK] = num;
    311             }
    312 
    313             fclose(displayDeviceFP);
    314         }
    315     }
    316 
    317     return 0;
    318 }
    319 
    320 bool Overlay::displayCommit(const int& fd) {
    321     //Commit
    322     struct mdp_display_commit info;
    323     memset(&info, 0, sizeof(struct mdp_display_commit));
    324     info.flags = MDP_DISPLAY_COMMIT_OVERLAY;
    325     if(!mdp_wrapper::displayCommit(fd, info)) {
    326        ALOGE("%s: commit failed", __func__);
    327        return false;
    328     }
    329     return true;
    330 }
    331 
    332 void Overlay::dump() const {
    333 #if PIPE_DEBUG
    334     if(strlen(mDumpStr)) { //dump only on state change
    335         ALOGD("%s\n", mDumpStr);
    336     }
    337 #endif
    338 }
    339 
    340 void Overlay::getDump(char *buf, size_t len) {
    341     int totalPipes = 0;
    342     const char *str = "\nOverlay State\n\n";
    343     strncat(buf, str, strlen(str));
    344     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
    345         if(mPipeBook[i].valid()) {
    346             mPipeBook[i].mPipe->getDump(buf, len);
    347             char str[64] = {'\0'};
    348             snprintf(str, 64, "Display=%d\n\n", mPipeBook[i].mDisplay);
    349             strncat(buf, str, strlen(str));
    350             totalPipes++;
    351         }
    352     }
    353     char str_pipes[64] = {'\0'};
    354     snprintf(str_pipes, 64, "Pipes=%d\n\n", totalPipes);
    355     strncat(buf, str_pipes, strlen(str_pipes));
    356 }
    357 
    358 void Overlay::clear(int dpy) {
    359     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
    360         if (mPipeBook[i].mDisplay == dpy) {
    361             // Mark as available for this round
    362             PipeBook::resetUse(i);
    363             PipeBook::resetAllocation(i);
    364             if(mPipeBook[i].valid()) {
    365                 mPipeBook[i].mPipe->forceSet();
    366             }
    367         }
    368     }
    369 }
    370 
    371 void Overlay::PipeBook::init() {
    372     mPipe = NULL;
    373     mDisplay = DPY_UNUSED;
    374     mMixer = MIXER_UNUSED;
    375 }
    376 
    377 void Overlay::PipeBook::destroy() {
    378     if(mPipe) {
    379         delete mPipe;
    380         mPipe = NULL;
    381     }
    382     mDisplay = DPY_UNUSED;
    383     mMixer = MIXER_UNUSED;
    384 }
    385 
    386 Overlay* Overlay::sInstance = 0;
    387 int Overlay::sDpyFbMap[DPY_MAX] = {0, -1, -1};
    388 int Overlay::sDMAMode = DMA_LINE_MODE;
    389 int Overlay::sForceSetBitmap = 0;
    390 int Overlay::PipeBook::NUM_PIPES = 0;
    391 int Overlay::PipeBook::sPipeUsageBitmap = 0;
    392 int Overlay::PipeBook::sLastUsageBitmap = 0;
    393 int Overlay::PipeBook::sAllocatedBitmap = 0;
    394 utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
    395     {utils::OV_MDP_PIPE_ANY};
    396 
    397 }; // namespace overlay
    398