1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. 4 * Not a Contribution, Apache license notifications and license are retained 5 * for attribution purposes only. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18*/ 19 20#include "overlayRotator.h" 21#include "overlayUtils.h" 22#include "mdp_version.h" 23#include "sync/sync.h" 24#include "gr.h" 25 26namespace ovutils = overlay::utils; 27 28namespace overlay { 29 30//============Rotator========================= 31 32Rotator::Rotator() { 33 char property[PROPERTY_VALUE_MAX]; 34 mRotCacheDisabled = false; 35 if((property_get("debug.rotcache.disable", property, NULL) > 0) && 36 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) || 37 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) { 38 /* Used in debugging to turnoff rotator caching */ 39 mRotCacheDisabled = true; 40 } 41} 42 43Rotator::~Rotator() {} 44 45Rotator* Rotator::getRotator() { 46 int type = getRotatorHwType(); 47 if(type == TYPE_MDP) { 48 return new MdpRot(); //will do reset 49 } else if(type == TYPE_MDSS) { 50 return new MdssRot(); 51 } else { 52 ALOGE("%s Unknown h/w type %d", __FUNCTION__, type); 53 return NULL; 54 } 55} 56 57int Rotator::getDownscaleFactor(const int& srcW, const int& srcH, 58 const int& dstW, const int& dstH, const uint32_t& mdpFormat, 59 const bool& isInterlaced) { 60 if(getRotatorHwType() == TYPE_MDSS) { 61 return MdssRot::getDownscaleFactor(srcW, srcH, dstW, dstH, 62 mdpFormat, isInterlaced); 63 } 64 return MdpRot::getDownscaleFactor(srcW, srcH, dstW, dstH, 65 mdpFormat, isInterlaced); 66} 67 68uint32_t Rotator::calcOutputBufSize(const utils::Whf& destWhf) { 69 //dummy aligned w & h. 70 int alW = 0, alH = 0; 71 int halFormat = ovutils::getHALFormat(destWhf.format); 72 //A call into gralloc/memalloc 73 return getBufferSizeAndDimensions( 74 destWhf.w, destWhf.h, halFormat, alW, alH); 75} 76 77int Rotator::getRotatorHwType() { 78 int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion(); 79 if (mdpVersion == qdutils::MDSS_V5) 80 return TYPE_MDSS; 81 return TYPE_MDP; 82} 83 84bool Rotator::isRotCached(int fd, uint32_t offset) const { 85 if(mRotCacheDisabled or rotConfChanged() or rotDataChanged(fd,offset)) 86 return false; 87 return true; 88} 89 90bool Rotator::rotDataChanged(int fd, uint32_t offset) const { 91 /* fd and offset are the attributes of the current rotator input buffer. 92 * At this instance, getSrcMemId() and getSrcOffset() return the 93 * attributes of the previous rotator input buffer */ 94 if( (fd == getSrcMemId()) and (offset == getSrcOffset()) ) 95 return false; 96 return true; 97} 98 99//============RotMem========================= 100 101bool RotMem::close() { 102 bool ret = true; 103 if(valid()) { 104 if(mem.close() == false) { 105 ALOGE("%s error in closing rot mem", __FUNCTION__); 106 ret = false; 107 } 108 } 109 return ret; 110} 111 112RotMem::RotMem() : mCurrIndex(0) { 113 utils::memset0(mRotOffset); 114 for(int i = 0; i < ROT_NUM_BUFS; i++) { 115 mRelFence[i] = -1; 116 } 117} 118 119RotMem::~RotMem() { 120 for(int i = 0; i < ROT_NUM_BUFS; i++) { 121 ::close(mRelFence[i]); 122 mRelFence[i] = -1; 123 } 124} 125 126void RotMem::setCurrBufReleaseFd(const int& fence) { 127 int ret = 0; 128 129 if(mRelFence[mCurrIndex] >= 0) { 130 //Wait for previous usage of this buffer to be over. 131 //Can happen if rotation takes > vsync and a fast producer. i.e queue 132 //happens in subsequent vsyncs either because content is 60fps or 133 //because the producer is hasty sometimes. 134 ret = sync_wait(mRelFence[mCurrIndex], 1000); 135 if(ret < 0) { 136 ALOGE("%s: sync_wait error!! error no = %d err str = %s", 137 __FUNCTION__, errno, strerror(errno)); 138 } 139 ::close(mRelFence[mCurrIndex]); 140 } 141 mRelFence[mCurrIndex] = fence; 142} 143 144void RotMem::setPrevBufReleaseFd(const int& fence) { 145 uint32_t numRotBufs = mem.numBufs(); 146 uint32_t prevIndex = (mCurrIndex + numRotBufs - 1) % (numRotBufs); 147 148 if(mRelFence[prevIndex] >= 0) { 149 /* No need of any wait as nothing will be written into this 150 * buffer by the rotator (this func is called when rotator is 151 * in cache mode) */ 152 ::close(mRelFence[prevIndex]); 153 } 154 155 mRelFence[prevIndex] = fence; 156} 157 158//============RotMgr========================= 159RotMgr * RotMgr::sRotMgr = NULL; 160 161RotMgr* RotMgr::getInstance() { 162 if(sRotMgr == NULL) { 163 sRotMgr = new RotMgr(); 164 } 165 return sRotMgr; 166} 167 168RotMgr::RotMgr() { 169 for(int i = 0; i < MAX_ROT_SESS; i++) { 170 mRot[i] = 0; 171 } 172 mUseCount = 0; 173 mRotDevFd = -1; 174} 175 176RotMgr::~RotMgr() { 177 clear(); 178} 179 180void RotMgr::configBegin() { 181 //Reset the number of objects used 182 mUseCount = 0; 183} 184 185void RotMgr::configDone() { 186 //Remove the top most unused objects. Videos come and go. 187 for(int i = mUseCount; i < MAX_ROT_SESS; i++) { 188 if(mRot[i]) { 189 delete mRot[i]; 190 mRot[i] = 0; 191 } 192 } 193} 194 195Rotator* RotMgr::getNext() { 196 //Return a rot object, creating one if necessary 197 overlay::Rotator *rot = NULL; 198 if(mUseCount >= MAX_ROT_SESS) { 199 ALOGW("%s, MAX rotator sessions reached, request rejected", __func__); 200 } else { 201 if(mRot[mUseCount] == NULL) 202 mRot[mUseCount] = overlay::Rotator::getRotator(); 203 rot = mRot[mUseCount++]; 204 } 205 return rot; 206} 207 208void RotMgr::clear() { 209 //Brute force obj destruction, helpful in suspend. 210 for(int i = 0; i < MAX_ROT_SESS; i++) { 211 if(mRot[i]) { 212 delete mRot[i]; 213 mRot[i] = 0; 214 } 215 } 216 mUseCount = 0; 217 ::close(mRotDevFd); 218 mRotDevFd = -1; 219} 220 221void RotMgr::getDump(char *buf, size_t len) { 222 for(int i = 0; i < MAX_ROT_SESS; i++) { 223 if(mRot[i]) { 224 mRot[i]->getDump(buf, len); 225 } 226 } 227 char str[4] = {'\0'}; 228 snprintf(str, 4, "\n"); 229 strlcat(buf, str, len); 230} 231 232int RotMgr::getRotDevFd() { 233 if(mRotDevFd < 0 && Rotator::getRotatorHwType() == Rotator::TYPE_MDSS) { 234 mRotDevFd = ::open("/dev/graphics/fb0", O_RDWR, 0); 235 if(mRotDevFd < 0) { 236 ALOGE("%s failed to open fb0", __FUNCTION__); 237 } 238 } 239 return mRotDevFd; 240} 241 242} 243