cc18cfed4c
Draw sequence in hwc_set --eglSwapBuffers --wait for fb_post. Its ok to draw to External only at this point. --draw to external | Parallel with PAN --commit to external | Parallel with PAN --wait for pan (happening in fb_post) to finish. Call MSMFB_OVERLAY_SET ioctl only when params change. These thing together ensure a correct sequence and should fix tearing and stuttering, the latter assuming there are no other display pipeline delays. Change-Id: Ibb0ad8485fa6b30dc6ac07ae8b25a760941c08ce (cherry picked from commit c50c90863e41e31ecfe6963396b5def35e9dca34)
209 lines
5.7 KiB
C++
209 lines
5.7 KiB
C++
/*
|
|
* 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::init(uint32_t fbnum) {
|
|
// FD init
|
|
if(!utils::openDev(mFd, fbnum,
|
|
Res::fbPath, O_RDWR)){
|
|
ALOGE("Ctrl failed to init fbnum=%d", fbnum);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void MdpCtrl::reset() {
|
|
utils::memset0(mOVInfo);
|
|
utils::memset0(mLkgo);
|
|
mOVInfo.id = MSMFB_NEW_REQUEST;
|
|
mLkgo.id = MSMFB_NEW_REQUEST;
|
|
mOrientation = utils::OVERLAY_TRANSFORM_0;
|
|
mRotUsed = false;
|
|
}
|
|
|
|
bool MdpCtrl::close() {
|
|
if(MSMFB_NEW_REQUEST == static_cast<int>(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::setSource(const utils::PipeArgs& args) {
|
|
|
|
setSrcWhf(args.whf);
|
|
|
|
//TODO These are hardcoded. Can be moved out of setSource.
|
|
mOVInfo.alpha = 0xff;
|
|
mOVInfo.transp_mask = 0xffffffff;
|
|
|
|
//TODO These calls should ideally be a part of setPipeParams API
|
|
setFlags(args.mdpFlags);
|
|
setZ(args.zorder);
|
|
setIsFg(args.isFg);
|
|
return true;
|
|
}
|
|
|
|
bool MdpCtrl::setCrop(const utils::Dim& d) {
|
|
setSrcRectDim(d);
|
|
return true;
|
|
}
|
|
|
|
bool MdpCtrl::setPosition(const overlay::utils::Dim& d,
|
|
int fbw, int fbh)
|
|
{
|
|
ovutils::Dim dim(d);
|
|
ovutils::Dim ovsrcdim = getSrcRectDim();
|
|
// Scaling of upto a max of 20 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;
|
|
}
|
|
|
|
setDstRectDim(dim);
|
|
return true;
|
|
}
|
|
|
|
bool MdpCtrl::setTransform(const utils::eTransform& orient,
|
|
const bool& rotUsed) {
|
|
int rot = utils::getMdpOrient(orient);
|
|
setUserData(rot);
|
|
//getMdpOrient will switch the flips if the source is 90 rotated.
|
|
//Clients in Android dont factor in 90 rotation while deciding the flip.
|
|
mOrientation = static_cast<utils::eTransform>(rot);
|
|
|
|
//Rotator can be requested by client even if layer has 0 orientation.
|
|
mRotUsed = rotUsed;
|
|
return true;
|
|
}
|
|
|
|
void MdpCtrl::doTransform() {
|
|
adjustSrcWhf(mRotUsed);
|
|
setRotationFlags();
|
|
//180 will be H + V
|
|
//270 will be H + V + 90
|
|
if(mOrientation & utils::OVERLAY_TRANSFORM_FLIP_H) {
|
|
overlayTransFlipH();
|
|
}
|
|
if(mOrientation & utils::OVERLAY_TRANSFORM_FLIP_V) {
|
|
overlayTransFlipV();
|
|
}
|
|
if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) {
|
|
overlayTransRot90();
|
|
}
|
|
}
|
|
|
|
bool MdpCtrl::set() {
|
|
//deferred calcs, so APIs could be called in any order.
|
|
doTransform();
|
|
if(this->ovChanged()) {
|
|
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();
|
|
return false;
|
|
}
|
|
this->save();
|
|
}
|
|
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;
|
|
}
|
|
|
|
//Adjust width, height, format if rotator is used.
|
|
void MdpCtrl::adjustSrcWhf(const bool& rotUsed) {
|
|
if(rotUsed) {
|
|
utils::Whf whf = getSrcWhf();
|
|
if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
|
|
whf.format == MDP_Y_CBCR_H2V2_TILE) {
|
|
whf.w = utils::alignup(whf.w, 64);
|
|
whf.h = utils::alignup(whf.h, 32);
|
|
}
|
|
//For example: If original format is tiled, rotator outputs non-tiled,
|
|
//so update mdp's src fmt to that.
|
|
whf.format = utils::getRotOutFmt(whf.format);
|
|
setSrcWhf(whf);
|
|
}
|
|
}
|
|
|
|
void MdpCtrl::dump() const {
|
|
ALOGE("== Dump MdpCtrl start ==");
|
|
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
|