/* * Copyright (C) 2008 The Android Open Source Project * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "overlayUtils.h" #include "overlayMdp.h" #undef ALOG_TAG #define ALOG_TAG "overlay" namespace ovutils = overlay::utils; namespace overlay { bool MdpCtrl::open(uint32_t fbnum) { // FD open if(!utils::openDev(mFd, fbnum, Res::devTemplate, O_RDWR)){ ALOGE("Ctrl failed to open fbnum=%d", fbnum); return false; } return true; } void MdpCtrl::reset() { utils::memset0(mOVInfo); utils::memset0(mLkgo); mOVInfo.id = -1; mLkgo.id = -1; } bool MdpCtrl::close() { if(-1 == static_cast(mOVInfo.id)) return true; if(!mdp_wrapper::unsetOverlay(mFd.getFD(), mOVInfo.id)) { ALOGE("MdpCtrl close error in unset"); return false; } reset(); if(!mFd.close()) { return false; } return true; } bool MdpCtrl::getScreenInfo(overlay::utils::ScreenInfo& info) { fb_fix_screeninfo finfo; if (!mdp_wrapper::getFScreenInfo(mFd.getFD(), finfo)) { return false; } fb_var_screeninfo vinfo; if (!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) { return false; } info.mFBWidth = vinfo.xres; info.mFBHeight = vinfo.yres; info.mFBbpp = vinfo.bits_per_pixel; info.mFBystride = finfo.line_length; return true; } bool MdpCtrl::get() { mdp_overlay ov; ov.id = mOVInfo.id; if (!mdp_wrapper::getOverlay(mFd.getFD(), ov)) { ALOGE("MdpCtrl get failed"); return false; } mOVInfo = ov; return true; } // that is the second part of original setParameter function void MdpCtrl::setSrcFormat(const utils::Whf& whf) { //By default mdp src format is the same as buffer's mOVInfo.src.format = whf.format; //If rotation is used and input formats are tiled then output of rotator is //non-tiled. // FIXME mRotInfo.enable = 1; for enable if (getUserData()) { // if rotations enabled in MdpCtrl if (whf.format == MDP_Y_CRCB_H2V2_TILE) mOVInfo.src.format = MDP_Y_CRCB_H2V2; else if (whf.format == MDP_Y_CBCR_H2V2_TILE) mOVInfo.src.format = MDP_Y_CBCR_H2V2; return; } } bool MdpCtrl::set() { if(!this->ovChanged()) { return true; // nothing todo here. } if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) { ALOGE("MdpCtrl failed to setOverlay, restoring last known " "good ov info"); mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo); mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo); this->restore(); // FIXME, do we need to set the old one? return false; } this->save(); return true; } bool MdpCtrl::setPosition(const overlay::utils::Dim& d, int fbw, int fbh) { // Validatee against FB size if(!d.check(fbw, fbh)) { ALOGE("MdpCtrl setPosition failed dest dim violate screen limits"); return false; } ovutils::Dim dim(d); ovutils::Dim ovsrcdim = getSrcRectDim(); // Scaling of upto a max of 8 times supported if(dim.w >(ovsrcdim.w * ovutils::HW_OV_MAGNIFICATION_LIMIT)){ dim.w = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.w; dim.x = (fbw - dim.w) / 2; } if(dim.h >(ovsrcdim.h * ovutils::HW_OV_MAGNIFICATION_LIMIT)) { dim.h = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.h; dim.y = (fbh - dim.h) / 2; } //dim.even_out(); setDstRectDim(dim); return true; } void MdpCtrl::updateSource(RotatorBase* r, const utils::PipeArgs& args, const utils::ScreenInfo& info) { utils::Whf whf(args.whf); mOVInfo.src.width = whf.w; mOVInfo.src.height = whf.h; mOVInfo.src_rect.x = 0; mOVInfo.src_rect.y = 0; mOVInfo.dst_rect.x = 0; mOVInfo.dst_rect.y = 0; mOVInfo.dst_rect.w = whf.w; mOVInfo.dst_rect.h = whf.h; mOVInfo.src.format = whf.format; if(whf.format == MDP_Y_CRCB_H2V2_TILE || (whf.format == MDP_Y_CBCR_H2V2_TILE)) { // passing by value, setInfo fills it and return by val mOVInfo = r->setInfo(args, mOVInfo); } else { mOVInfo.src_rect.w = whf.w; mOVInfo.src_rect.h = whf.h; } if (whf.w > info.mFBWidth) mOVInfo.dst_rect.w = info.mFBWidth; if (whf.h > info.mFBHeight) mOVInfo.dst_rect.h = info.mFBHeight; mSize = whf.size; } bool MdpCtrl::setInfo(RotatorBase* r, const utils::PipeArgs& args, const utils::ScreenInfo& info) { // new request utils::Whf whf(args.whf); mOVInfo.id = MSMFB_NEW_REQUEST; updateSource(r, args, info); setUserData(0); mOVInfo.alpha = 0xff; mOVInfo.transp_mask = 0xffffffff; setZ(args.zorder); setFlags(args.mdpFlags); setWait(args.wait); setIsFg(args.isFg); mSize = whf.size; return true; } bool MdpCtrl::setCrop(const utils::Dim& cdim) { utils::Dim d(cdim); const utils::Whf ovwhf = getSrcWhf(); int udata = getUserData(); switch(udata) { case MDP_ROT_NOP: break; // nothing to do here case MDP_ROT_90: case MDP_ROT_90 | MDP_FLIP_UD: case MDP_ROT_90 | MDP_FLIP_LR: { if (ovwhf.w < (d.y + d.h)) { ALOGE("MdpCtrl setCrop failed ROT 90 udata=%d", udata); d.dump(); this->dump(); return false; } uint32_t tmp = d.x; d.x = ovwhf.w - (d.y + d.h); d.y = tmp; utils::swap(d.w, d.h); }break; case MDP_ROT_270: { if (ovwhf.h < (d.x + d.w)) { ALOGE("MdpCtrl setCrop failed ROT 270 udata=%d", udata); d.dump(); this->dump(); return false; } uint32_t tmp = d.y; d.y = ovwhf.h - (d.x + d.w); d.x = tmp; utils::swap(d.w, d.h); }break; case MDP_ROT_180: { if ((ovwhf.h < (d.y + d.h)) || (ovwhf.w < ( d.x + d.w))) { ALOGE("MdpCtrl setCrop failed ROT 180 udata=%d", udata); d.dump(); this->dump(); return false; } d.x = ovwhf.w - (d.x + d.w); d.y = ovwhf.h - (d.y + d.h); }break; default: if(!(udata & (MDP_FLIP_UD | MDP_FLIP_LR))) { ALOGE("MdpCtrl setCrop unknown rot %d", udata); return false; } } if(getSrcRectDim() == d) { return true; // Nothing to do here } utils::normalizeCrop(d.x, d.w); utils::normalizeCrop(d.y, d.h); setSrcRectDim(d); return true; } void MdpCtrl::dump() const { ALOGE("== Dump MdpCtrl start =="); ALOGE("size=%d", mSize); mFd.dump(); mdp_wrapper::dump("mOVInfo", mOVInfo); ALOGE("== Dump MdpCtrl end =="); } void MdpData::dump() const { ALOGE("== Dump MdpData start =="); mFd.dump(); mdp_wrapper::dump("mOvData", mOvData); ALOGE("== Dump MdpData end =="); } void MdpCtrl3D::dump() const { ALOGE("== Dump MdpCtrl start =="); mFd.dump(); ALOGE("== Dump MdpCtrl end =="); } } // overlay