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