Home | History | Annotate | Download | only in liboverlay
      1 /*
      2 * Copyright (c) 2011-2014, 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 <dlfcn.h>
     31 #include "overlay.h"
     32 #include "pipes/overlayGenPipe.h"
     33 #include "mdp_version.h"
     34 #include "qdMetaData.h"
     35 #include "qd_utils.h"
     36 
     37 namespace overlay {
     38 using namespace utils;
     39 using namespace qdutils;
     40 
     41 Overlay::Overlay() {
     42     int numPipes = qdutils::MDPVersion::getInstance().getTotalPipes();
     43     PipeBook::NUM_PIPES = (numPipes <= utils::OV_MAX)? numPipes : utils::OV_MAX;
     44     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
     45         mPipeBook[i].init();
     46     }
     47 
     48     initScalar();
     49     setDMAMultiplexingSupported();
     50 }
     51 
     52 Overlay::~Overlay() {
     53     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
     54         mPipeBook[i].destroy();
     55     }
     56     destroyScalar();
     57 }
     58 
     59 void Overlay::configBegin() {
     60     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
     61         //Mark as available for this round.
     62         PipeBook::resetUse(i);
     63         PipeBook::resetAllocation(i);
     64     }
     65 }
     66 
     67 void Overlay::configDone() {
     68     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
     69         if((PipeBook::isNotUsed(i) && !sessionInProgress((eDest)i)) ||
     70                     isSessionEnded((eDest)i)) {
     71             //Forces UNSET on pipes, flushes rotator memory and session, closes
     72             //fds
     73             mPipeBook[i].destroy();
     74         }
     75     }
     76     PipeBook::save();
     77 }
     78 
     79 int Overlay::getPipeId(utils::eDest dest) {
     80     return mPipeBook[(int)dest].mPipe->getPipeId();
     81 }
     82 
     83 eDest Overlay::getDest(int pipeid) {
     84     eDest dest = OV_INVALID;
     85     // finding the dest corresponding to the given pipe
     86     for(int i=0; i < PipeBook::NUM_PIPES; ++i) {
     87         if(mPipeBook[i].valid() && mPipeBook[i].mPipe->getPipeId() == pipeid) {
     88             return (eDest)i;
     89         }
     90     }
     91     return dest;
     92 }
     93 
     94 eDest Overlay::reservePipe(int pipeid) {
     95     eDest dest = getDest(pipeid);
     96     PipeBook::setAllocation((int)dest);
     97     return dest;
     98 }
     99 
    100 eDest Overlay::nextPipe(eMdpPipeType type, const PipeSpecs& pipeSpecs) {
    101     eDest dest = OV_INVALID;
    102     int dpy = pipeSpecs.dpy;
    103     int mixer = pipeSpecs.mixer;
    104     int formatType = pipeSpecs.formatClass;
    105     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
    106         if( (type == OV_MDP_PIPE_ANY || //Pipe type match
    107              type == PipeBook::getPipeType((eDest)i)) &&
    108             (mPipeBook[i].mDisplay == DPY_UNUSED || //Free or same display
    109              mPipeBook[i].mDisplay == dpy) &&
    110             (mPipeBook[i].mMixer == MIXER_UNUSED || //Free or same mixer
    111              mPipeBook[i].mMixer == mixer) &&
    112             (mPipeBook[i].mFormatType == FORMAT_NONE || //Free or same format
    113              mPipeBook[i].mFormatType == formatType) &&
    114             PipeBook::isNotAllocated(i) && //Free pipe
    115             ( (sDMAMultiplexingSupported && dpy) ||
    116               !(sDMAMode == DMA_BLOCK_MODE && //DMA pipe in Line mode
    117                PipeBook::getPipeType((eDest)i) == OV_MDP_PIPE_DMA)) ){
    118               //DMA-Multiplexing is only supported for WB on 8x26
    119             dest = (eDest)i;
    120             PipeBook::setAllocation(i);
    121             break;
    122         }
    123     }
    124 
    125     if(dest != OV_INVALID) {
    126         int index = (int)dest;
    127         mPipeBook[index].mDisplay = dpy;
    128         mPipeBook[index].mMixer = mixer;
    129         mPipeBook[index].mFormatType = formatType;
    130         if(not mPipeBook[index].valid()) {
    131             mPipeBook[index].mPipe = new GenericPipe(dpy);
    132             mPipeBook[index].mSession = PipeBook::NONE;
    133         }
    134     }
    135 
    136     return dest;
    137 }
    138 
    139 utils::eDest Overlay::getPipe(const PipeSpecs& pipeSpecs) {
    140     if(MDPVersion::getInstance().is8x26()) {
    141         return getPipe_8x26(pipeSpecs);
    142     } else if(MDPVersion::getInstance().is8x16()) {
    143         return getPipe_8x16(pipeSpecs);
    144     } else if(MDPVersion::getInstance().is8x39()) {
    145         return getPipe_8x39(pipeSpecs);
    146     } else if(MDPVersion::getInstance().is8994()) {
    147         return getPipe_8994(pipeSpecs);
    148     }
    149 
    150     eDest dest = OV_INVALID;
    151 
    152     //The default behavior is to assume RGB and VG pipes have scalars
    153     if(pipeSpecs.formatClass == FORMAT_YUV) {
    154         return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
    155     } else if(pipeSpecs.fb == false) { //RGB App layers
    156         if(not pipeSpecs.needsScaling) {
    157             dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
    158         }
    159         if(dest == OV_INVALID) {
    160             dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
    161         }
    162         if(dest == OV_INVALID) {
    163             dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
    164         }
    165     } else { //FB layer
    166         dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
    167         if(dest == OV_INVALID) {
    168             dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
    169         }
    170         //Some features can cause FB to have scaling as well.
    171         //If we ever come to this block with FB needing scaling,
    172         //the screen will be black for a frame, since the FB won't get a pipe
    173         //but atleast this will prevent a hang
    174         if(dest == OV_INVALID and (not pipeSpecs.needsScaling)) {
    175             dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
    176         }
    177     }
    178     return dest;
    179 }
    180 
    181 utils::eDest Overlay::getPipe_8x26(const PipeSpecs& pipeSpecs) {
    182     //Use this to hide all the 8x26 requirements that cannot be humanly
    183     //described in a generic way
    184     eDest dest = OV_INVALID;
    185     if(pipeSpecs.formatClass == FORMAT_YUV) { //video
    186         return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
    187     } else if(pipeSpecs.fb == false) { //RGB app layers
    188         if((not pipeSpecs.needsScaling) and
    189           (not (pipeSpecs.numActiveDisplays > 1 &&
    190                 pipeSpecs.dpy == DPY_PRIMARY))) {
    191             dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
    192         }
    193         if(dest == OV_INVALID) {
    194             dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
    195         }
    196         if(dest == OV_INVALID) {
    197             dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
    198         }
    199     } else { //FB layer
    200         //For 8x26 Secondary we use DMA always for FB for inline rotation
    201         if(pipeSpecs.dpy == DPY_PRIMARY) {
    202             dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
    203             if(dest == OV_INVALID) {
    204                 dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
    205             }
    206         }
    207         if(dest == OV_INVALID and (not pipeSpecs.needsScaling) and
    208           (not (pipeSpecs.numActiveDisplays > 1 &&
    209                 pipeSpecs.dpy == DPY_PRIMARY))) {
    210             dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
    211         }
    212     }
    213     return dest;
    214 }
    215 
    216 utils::eDest Overlay::getPipe_8x16(const PipeSpecs& pipeSpecs) {
    217     //Having such functions help keeping the interface generic but code specific
    218     //and rife with assumptions
    219     eDest dest = OV_INVALID;
    220     if(pipeSpecs.formatClass == FORMAT_YUV or pipeSpecs.needsScaling) {
    221         return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
    222     } else {
    223         //Since this is a specific func, we can assume stuff like RGB pipe not
    224         //having scalar blocks
    225         dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
    226         if(dest == OV_INVALID) {
    227             dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
    228         }
    229         if(dest == OV_INVALID) {
    230             dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
    231         }
    232     }
    233     return dest;
    234 }
    235 
    236 utils::eDest Overlay::getPipe_8x39(const PipeSpecs& pipeSpecs) {
    237     //8x16 & 8x36 has same number of pipes, pipe-types & scaling capabilities.
    238     //Rely on 8x16 until we see a need to change.
    239     return getPipe_8x16(pipeSpecs);
    240 }
    241 
    242 utils::eDest Overlay::getPipe_8994(const PipeSpecs& pipeSpecs) {
    243     //If DMA pipes need to be used in block mode for downscale, there could be
    244     //cases where consecutive rounds need separate modes, which cannot be
    245     //supported since we at least need 1 round in between where the DMA is
    246     //unused
    247     eDest dest = OV_INVALID;
    248     if(pipeSpecs.formatClass == FORMAT_YUV) {
    249         return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
    250     } else {
    251         dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
    252         if(dest == OV_INVALID) {
    253             dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
    254         }
    255         if(dest == OV_INVALID and not pipeSpecs.needsScaling) {
    256             dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
    257         }
    258     }
    259     return dest;
    260 }
    261 
    262 void Overlay::endAllSessions() {
    263     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
    264         if(mPipeBook[i].valid() && mPipeBook[i].mSession==PipeBook::START)
    265             mPipeBook[i].mSession = PipeBook::END;
    266     }
    267 }
    268 
    269 bool Overlay::isPipeTypeAttached(eMdpPipeType type) {
    270     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
    271         if(type == PipeBook::getPipeType((eDest)i) &&
    272                 mPipeBook[i].mDisplay != DPY_UNUSED) {
    273             return true;
    274         }
    275     }
    276     return false;
    277 }
    278 
    279 int Overlay::comparePipePriority(utils::eDest pipe1Index,
    280         utils::eDest pipe2Index) {
    281     validate((int)pipe1Index);
    282     validate((int)pipe2Index);
    283     uint8_t pipe1Prio = mPipeBook[(int)pipe1Index].mPipe->getPriority();
    284     uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
    285     if(pipe1Prio > pipe2Prio)
    286         return -1;
    287     if(pipe1Prio < pipe2Prio)
    288         return 1;
    289     return 0;
    290 }
    291 
    292 bool Overlay::commit(utils::eDest dest) {
    293     bool ret = false;
    294     validate((int)dest);
    295 
    296     if(mPipeBook[dest].mPipe->commit()) {
    297         ret = true;
    298         PipeBook::setUse((int)dest);
    299     } else {
    300         clear(mPipeBook[dest].mDisplay);
    301     }
    302     return ret;
    303 }
    304 
    305 bool Overlay::queueBuffer(int fd, uint32_t offset,
    306         utils::eDest dest) {
    307     bool ret = false;
    308     validate((int)dest);
    309     //Queue only if commit() has succeeded (and the bit set)
    310     if(PipeBook::isUsed((int)dest)) {
    311         ret = mPipeBook[dest].mPipe->queueBuffer(fd, offset);
    312     }
    313     return ret;
    314 }
    315 
    316 void Overlay::setCrop(const utils::Dim& d,
    317         utils::eDest dest) {
    318     validate((int)dest);
    319     mPipeBook[dest].mPipe->setCrop(d);
    320 }
    321 
    322 void Overlay::setColor(const uint32_t color,
    323         utils::eDest dest) {
    324     validate((int)dest);
    325     mPipeBook[dest].mPipe->setColor(color);
    326 }
    327 
    328 void Overlay::setPosition(const utils::Dim& d,
    329         utils::eDest dest) {
    330     validate((int)dest);
    331     mPipeBook[dest].mPipe->setPosition(d);
    332 }
    333 
    334 void Overlay::setTransform(const int orient,
    335         utils::eDest dest) {
    336     validate((int)dest);
    337 
    338     utils::eTransform transform =
    339             static_cast<utils::eTransform>(orient);
    340     mPipeBook[dest].mPipe->setTransform(transform);
    341 
    342 }
    343 
    344 void Overlay::setSource(const utils::PipeArgs args,
    345         utils::eDest dest) {
    346     validate((int)dest);
    347 
    348     setPipeType(dest, PipeBook::getPipeType(dest));
    349     mPipeBook[dest].mPipe->setSource(args);
    350 }
    351 
    352 void Overlay::setVisualParams(const MetaData_t& metadata, utils::eDest dest) {
    353     validate((int)dest);
    354     mPipeBook[dest].mPipe->setVisualParams(metadata);
    355 }
    356 
    357 void Overlay::setPipeType(utils::eDest pipeIndex,
    358         const utils::eMdpPipeType pType) {
    359     mPipeBook[pipeIndex].mPipe->setPipeType(pType);
    360 }
    361 
    362 Overlay* Overlay::getInstance() {
    363     if(sInstance == NULL) {
    364         sInstance = new Overlay();
    365     }
    366     return sInstance;
    367 }
    368 
    369 // Clears any VG pipes allocated to the fb devices
    370 // Generates a LUT for pipe types.
    371 int Overlay::initOverlay() {
    372     int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
    373     int numPipesXType[OV_MDP_PIPE_ANY] = {0};
    374     numPipesXType[OV_MDP_PIPE_RGB] =
    375             qdutils::MDPVersion::getInstance().getRGBPipes();
    376     numPipesXType[OV_MDP_PIPE_VG] =
    377             qdutils::MDPVersion::getInstance().getVGPipes();
    378     numPipesXType[OV_MDP_PIPE_DMA] =
    379             qdutils::MDPVersion::getInstance().getDMAPipes();
    380 
    381     int index = 0;
    382     for(int X = 0; X < (int)OV_MDP_PIPE_ANY; X++) { //iterate over types
    383         for(int j = 0; j < numPipesXType[X]; j++) { //iterate over num
    384             PipeBook::pipeTypeLUT[index] = (utils::eMdpPipeType)X;
    385             index++;
    386         }
    387     }
    388 
    389     if (mdpVersion < qdutils::MDSS_V5 && mdpVersion > qdutils::MDP_V3_0_5) {
    390         msmfb_mixer_info_req  req;
    391         mdp_mixer_info *minfo = NULL;
    392         char name[64];
    393         int fd = -1;
    394         for(int i = 0; i < MAX_FB_DEVICES; i++) {
    395             snprintf(name, 64, FB_DEVICE_TEMPLATE, i);
    396             ALOGD("initoverlay:: opening the device:: %s", name);
    397             fd = ::open(name, O_RDWR, 0);
    398             if(fd < 0) {
    399                 ALOGE("cannot open framebuffer(%d)", i);
    400                 return -1;
    401             }
    402             //Get the mixer configuration */
    403             req.mixer_num = i;
    404             if (ioctl(fd, MSMFB_MIXER_INFO, &req) == -1) {
    405                 ALOGE("ERROR: MSMFB_MIXER_INFO ioctl failed");
    406                 close(fd);
    407                 return -1;
    408             }
    409             minfo = req.info;
    410             for (int j = 0; j < req.cnt; j++) {
    411                 ALOGD("ndx=%d num=%d z_order=%d", minfo->pndx, minfo->pnum,
    412                       minfo->z_order);
    413                 // except the RGB base layer with z_order of -1, clear any
    414                 // other pipes connected to mixer.
    415                 if((minfo->z_order) != -1) {
    416                     int index = minfo->pndx;
    417                     ALOGD("Unset overlay with index: %d at mixer %d", index, i);
    418                     if(ioctl(fd, MSMFB_OVERLAY_UNSET, &index) == -1) {
    419                         ALOGE("ERROR: MSMFB_OVERLAY_UNSET failed");
    420                         close(fd);
    421                         return -1;
    422                     }
    423                 }
    424                 minfo++;
    425             }
    426             close(fd);
    427             fd = -1;
    428         }
    429     }
    430 
    431     FILE *displayDeviceFP = NULL;
    432     char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
    433     char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
    434     const char *strDtvPanel = "dtv panel";
    435     const char *strWbPanel = "writeback panel";
    436 
    437     for(int num = 1; num < MAX_FB_DEVICES; num++) {
    438         snprintf (msmFbTypePath, sizeof(msmFbTypePath),
    439                 "/sys/class/graphics/fb%d/msm_fb_type", num);
    440         displayDeviceFP = fopen(msmFbTypePath, "r");
    441 
    442         if(displayDeviceFP){
    443             fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
    444                     displayDeviceFP);
    445 
    446             if(strncmp(fbType, strDtvPanel, strlen(strDtvPanel)) == 0) {
    447                 sDpyFbMap[DPY_EXTERNAL] = num;
    448             } else if(strncmp(fbType, strWbPanel, strlen(strWbPanel)) == 0) {
    449                 sDpyFbMap[DPY_WRITEBACK] = num;
    450             }
    451 
    452             fclose(displayDeviceFP);
    453         }
    454     }
    455 
    456     return 0;
    457 }
    458 
    459 bool Overlay::displayCommit(const int& fd) {
    460     utils::Dim lRoi, rRoi;
    461     return displayCommit(fd, lRoi, rRoi);
    462 }
    463 
    464 bool Overlay::displayCommit(const int& fd, const utils::Dim& lRoi,
    465         const utils::Dim& rRoi) {
    466     //Commit
    467     struct mdp_display_commit info;
    468     memset(&info, 0, sizeof(struct mdp_display_commit));
    469     info.flags = MDP_DISPLAY_COMMIT_OVERLAY;
    470     info.l_roi.x = lRoi.x;
    471     info.l_roi.y = lRoi.y;
    472     info.l_roi.w = lRoi.w;
    473     info.l_roi.h = lRoi.h;
    474     info.r_roi.x = rRoi.x;
    475     info.r_roi.y = rRoi.y;
    476     info.r_roi.w = rRoi.w;
    477     info.r_roi.h = rRoi.h;
    478 
    479     if(!mdp_wrapper::displayCommit(fd, info)) {
    480         ALOGE("%s: commit failed", __func__);
    481         return false;
    482     }
    483     return true;
    484 }
    485 
    486 void Overlay::getDump(char *buf, size_t len) {
    487     int totalPipes = 0;
    488     const char *str = "\nOverlay State\n\n";
    489     strlcat(buf, str, len);
    490     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
    491         if(mPipeBook[i].valid()) {
    492             mPipeBook[i].mPipe->getDump(buf, len);
    493             char str[64] = {'\0'};
    494             snprintf(str, 64, "Display=%d\n\n", mPipeBook[i].mDisplay);
    495             strlcat(buf, str, len);
    496             totalPipes++;
    497         }
    498     }
    499     char str_pipes[64] = {'\0'};
    500     snprintf(str_pipes, 64, "Pipes=%d\n\n", totalPipes);
    501     strlcat(buf, str_pipes, len);
    502 }
    503 
    504 void Overlay::clear(int dpy) {
    505     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
    506         if (mPipeBook[i].mDisplay == dpy) {
    507             // Mark as available for this round
    508             PipeBook::resetUse(i);
    509             PipeBook::resetAllocation(i);
    510             if(getPipeId((utils::eDest)i) == -1) {
    511                 mPipeBook[i].destroy();
    512             }
    513         }
    514     }
    515 }
    516 
    517 bool Overlay::validateAndSet(const int& dpy, const int& fbFd) {
    518     GenericPipe* pipeArray[PipeBook::NUM_PIPES];
    519     memset(pipeArray, 0, sizeof(GenericPipe*)*(PipeBook::NUM_PIPES));
    520 
    521     int num = 0;
    522     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
    523         if(PipeBook::isUsed(i) && mPipeBook[i].valid() &&
    524                 mPipeBook[i].mDisplay == dpy) {
    525             pipeArray[num++] = mPipeBook[i].mPipe;
    526         }
    527     }
    528 
    529     //Protect against misbehaving clients
    530     return num ? GenericPipe::validateAndSet(pipeArray, num, fbFd) : true;
    531 }
    532 
    533 void Overlay::initScalar() {
    534     if(sLibScaleHandle == NULL) {
    535         sLibScaleHandle = dlopen("libscale.so", RTLD_NOW);
    536         if(sLibScaleHandle) {
    537             *(void **) &sFnProgramScale =
    538                     dlsym(sLibScaleHandle, "programScale");
    539         }
    540     }
    541 }
    542 
    543 void Overlay::destroyScalar() {
    544     if(sLibScaleHandle) {
    545         dlclose(sLibScaleHandle);
    546         sLibScaleHandle = NULL;
    547     }
    548 }
    549 
    550 void Overlay::PipeBook::init() {
    551     mPipe = NULL;
    552     mDisplay = DPY_UNUSED;
    553     mMixer = MIXER_UNUSED;
    554     mFormatType = FORMAT_NONE;
    555 }
    556 
    557 void Overlay::PipeBook::destroy() {
    558     if(mPipe) {
    559         delete mPipe;
    560         mPipe = NULL;
    561     }
    562     mDisplay = DPY_UNUSED;
    563     mMixer = MIXER_UNUSED;
    564     mFormatType = FORMAT_NONE;
    565     mSession = NONE;
    566 }
    567 
    568 Overlay* Overlay::sInstance = 0;
    569 int Overlay::sDpyFbMap[DPY_MAX] = {0, -1, -1, -1};
    570 int Overlay::sDMAMode = DMA_LINE_MODE;
    571 bool Overlay::sDMAMultiplexingSupported = false;
    572 bool Overlay::sDebugPipeLifecycle = false;
    573 int Overlay::PipeBook::NUM_PIPES = 0;
    574 int Overlay::PipeBook::sPipeUsageBitmap = 0;
    575 int Overlay::PipeBook::sLastUsageBitmap = 0;
    576 int Overlay::PipeBook::sAllocatedBitmap = 0;
    577 utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
    578     {utils::OV_MDP_PIPE_ANY};
    579 void *Overlay::sLibScaleHandle = NULL;
    580 int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
    581 
    582 }; // namespace overlay
    583