android_hardware_qcom_display/liboverlay/overlayMdp.h
Ricardo Cerqueira ad7f1aa0d3 liboverlay: Make sure the crop rectangles' dimensions are even
Even out the values for both dimensions and position on both src
and destination rects.
This fixes both over and underrun issues, especially with HD panels

Change-Id: I781792d69cad83f76c3c0a45a5179a731661c3cf
2012-10-06 00:41:06 -05:00

504 lines
12 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.
*/
#ifndef OVERLAY_MDP_H
#define OVERLAY_MDP_H
#include <linux/msm_mdp.h>
#include "overlayUtils.h"
#include "mdpWrapper.h"
namespace overlay{
/*
* Mdp Ctrl holds corresponding fd and MDP related struct.
* It is simple wrapper to MDP services
* */
class MdpCtrl {
public:
/* ctor reset */
explicit MdpCtrl();
/* dtor close */
~MdpCtrl();
/* init underlying device using fbnum */
bool init(uint32_t fbnum);
/* unset overlay, reset and close fd */
bool close();
/* reset and set ov id to -1 / MSMFB_NEW_REQUEST */
void reset();
/* get orient / user_data[0] */
int getOrient() const;
/* returns session id */
int getPipeId() const;
/* returns the fd associated to ctrl*/
int getFd() const;
/* Get screen info. out: info*/
bool getScreenInfo(utils::ScreenInfo& info);
/* overlay get */
bool get();
/* returns flags from mdp structure */
int getFlags() const;
/* set flags to mdp structure */
void setFlags(int f);
/* set z order */
void setZ(utils::eZorder z);
/* set isFg flag */
void setIsFg(utils::eIsFg isFg);
/* calls overlay set
* Set would always consult last good known ov instance.
* Only if it is different, set would actually exectue ioctl.
* On a sucess ioctl. last good known ov instance is updated */
bool set();
/* return a copy of src whf*/
utils::Whf getSrcWhf() const;
/* set src whf */
void setSrcWhf(const utils::Whf& whf);
/* adjust source width height format based on rot info */
void adjustSrcWhf(const bool& rotUsed);
/* swap src w/h*/
void swapSrcWH();
/* swap src rect w/h */
void swapSrcRectWH();
/* returns a copy to src rect dim */
utils::Dim getSrcRectDim() const;
/* set src/dst rect dim */
void setSrcRectDim(const utils::Dim d);
void setDstRectDim(const utils::Dim d);
/* returns a copy ro dst rect dim */
utils::Dim getDstRectDim() const;
/* returns user_data[0]*/
int getUserData() const;
/* sets user_data[0] */
void setUserData(int v);
/* return true if current overlay is different
* than last known good overlay */
bool ovChanged() const;
/* save mOVInfo to be last known good ov*/
void save();
/* restore last known good ov to be the current */
void restore();
/* Sets the source total width, height, format */
bool setSource(const utils::PipeArgs& pargs);
/*
* Sets ROI, the unpadded region, for source buffer.
* Should be called before a setPosition, for small clips.
* Dim - ROI dimensions.
*/
bool setCrop(const utils::Dim& d);
bool setTransform(const utils::eTransform& orient, const bool& rotUsed);
/* given a dim and w/h, set overlay dim */
bool setPosition(const utils::Dim& dim, int w, int h);
/* using user_data, sets/unsets roationvalue in mdp flags */
void setRotationFlags();
/* dump state of the object */
void dump() const;
private:
/* helper functions for overlayTransform */
void doTransform();
void overlayTransFlipH();
void overlayTransFlipV();
void overlayTransRot90();
utils::eTransform mOrientation; //Holds requested orientation
bool mRotUsed; //whether rotator should be used even if requested
//orientation is 0.
/* last good known ov info */
mdp_overlay mLkgo;
/* Actual overlay mdp structure */
mdp_overlay mOVInfo;
/* FD for the mdp fbnum */
OvFD mFd;
};
/* MDP 3D related ctrl */
class MdpCtrl3D {
public:
/* ctor reset data */
MdpCtrl3D();
/* calls MSMFB_OVERLAY_3D */
bool close();
/* set w/h. format is ignored*/
void setWh(const utils::Whf& whf);
/* set is_3d calls MSMFB_OVERLAY_3D */
bool useVirtualFB();
/* set fd to be used in ioctl */
void setFd(int fd);
/* dump */
void dump() const;
private:
/* reset */
void reset();
/* actual MSM 3D info */
msmfb_overlay_3d m3DOVInfo;
/* FD for the mdp 3D */
OvFD mFd;
};
/* MDP data */
class MdpData {
public:
/* ctor reset data */
explicit MdpData();
/* dtor close*/
~MdpData();
/* init FD */
bool init(uint32_t fbnum);
/* memset0 the underlying mdp object */
void reset();
/* close fd, and reset */
bool close();
/* set id of mdp data */
void setPipeId(int id);
/* return ses id of data */
int getPipeId() const;
/* get underlying fd*/
int getFd() const;
/* get memory_id */
int getSrcMemoryId() const;
/* calls wrapper play */
bool play(int fd, uint32_t offset);
/* dump state of the object */
void dump() const;
private:
/* actual overlay mdp data */
msmfb_overlay_data mOvData;
/* fd to mdp fbnum */
OvFD mFd;
};
//--------------Inlines---------------------------------
namespace utils {
inline bool openDev(OvFD& fd, int fbnum,
const char* const devpath,
int flags) {
return overlay::open(fd, fbnum, devpath, flags);
}
}
namespace {
// just a helper func for common operations x-(y+z)
int compute(uint32_t x, uint32_t y, uint32_t z) {
return x-(y+z);
}
}
///// MdpCtrl //////
inline MdpCtrl::MdpCtrl() {
reset();
}
inline MdpCtrl::~MdpCtrl() {
close();
}
inline int MdpCtrl::getOrient() const {
return getUserData();
}
inline int MdpCtrl::getPipeId() const {
return mOVInfo.id;
}
inline int MdpCtrl::getFd() const {
return mFd.getFD();
}
inline int MdpCtrl::getFlags() const {
return mOVInfo.flags;
}
inline void MdpCtrl::setFlags(int f) {
mOVInfo.flags = f;
}
inline void MdpCtrl::setZ(overlay::utils::eZorder z) {
mOVInfo.z_order = z;
}
inline void MdpCtrl::setIsFg(overlay::utils::eIsFg isFg) {
mOVInfo.is_fg = isFg;
}
inline bool MdpCtrl::ovChanged() const {
// 0 means same
if(0 == ::memcmp(&mOVInfo, &mLkgo, sizeof (mdp_overlay))) {
return false;
}
return true;
}
inline void MdpCtrl::save() {
if(static_cast<ssize_t>(mOVInfo.id) == MSMFB_NEW_REQUEST) {
ALOGE("MdpCtrl current ov has id -1, will not save");
return;
}
mLkgo = mOVInfo;
}
inline void MdpCtrl::restore() {
if(static_cast<ssize_t>(mLkgo.id) == MSMFB_NEW_REQUEST) {
ALOGE("MdpCtrl Lkgo ov has id -1, will not restore");
return;
}
mOVInfo = mLkgo;
}
inline overlay::utils::Whf MdpCtrl::getSrcWhf() const {
return utils::Whf( mOVInfo.src.width,
mOVInfo.src.height,
mOVInfo.src.format);
}
inline void MdpCtrl::setSrcWhf(const overlay::utils::Whf& whf) {
mOVInfo.src.width = whf.w;
mOVInfo.src.height = whf.h;
mOVInfo.src.format = whf.format;
}
inline overlay::utils::Dim MdpCtrl::getSrcRectDim() const {
return utils::Dim( mOVInfo.src_rect.x,
mOVInfo.src_rect.y,
mOVInfo.src_rect.w,
mOVInfo.src_rect.h);
}
inline void MdpCtrl::setSrcRectDim(const overlay::utils::Dim d) {
mOVInfo.src_rect.x = d.x;
mOVInfo.src_rect.y = d.y;
mOVInfo.src_rect.w = d.w;
mOVInfo.src_rect.h = d.h;
utils::even_ceil(mOVInfo.src_rect.x);
utils::even_ceil(mOVInfo.src_rect.y);
utils::even_floor(mOVInfo.src_rect.w);
utils::even_floor(mOVInfo.src_rect.h);
}
inline overlay::utils::Dim MdpCtrl::getDstRectDim() const {
return utils::Dim( mOVInfo.dst_rect.x,
mOVInfo.dst_rect.y,
mOVInfo.dst_rect.w,
mOVInfo.dst_rect.h);
}
inline void MdpCtrl::setDstRectDim(const overlay::utils::Dim d) {
mOVInfo.dst_rect.x = d.x;
mOVInfo.dst_rect.y = d.y;
mOVInfo.dst_rect.w = d.w;
mOVInfo.dst_rect.h = d.h;
utils::even_ceil(mOVInfo.dst_rect.x);
utils::even_ceil(mOVInfo.dst_rect.y);
utils::even_floor(mOVInfo.dst_rect.w);
utils::even_floor(mOVInfo.dst_rect.h);
}
inline int MdpCtrl::getUserData() const { return mOVInfo.user_data[0]; }
inline void MdpCtrl::setUserData(int v) { mOVInfo.user_data[0] = v; }
inline void MdpCtrl::setRotationFlags() {
const int u = getUserData();
if (u == MDP_ROT_90 || u == MDP_ROT_270)
mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
else
mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90;
}
inline void MdpCtrl::swapSrcWH() {
utils::swap(mOVInfo.src.width,
mOVInfo.src.height);
}
inline void MdpCtrl::swapSrcRectWH() {
utils::swap(mOVInfo.src_rect.w,
mOVInfo.src_rect.h);
}
inline void MdpCtrl::overlayTransFlipH()
{
utils::Dim d = getSrcRectDim();
utils::Whf whf = getSrcWhf();
d.x = compute(whf.w, d.x, d.w);
setSrcRectDim(d);
}
inline void MdpCtrl::overlayTransFlipV()
{
utils::Dim d = getSrcRectDim();
utils::Whf whf = getSrcWhf();
d.y = compute(whf.h, d.y, d.h);
setSrcRectDim(d);
}
inline void MdpCtrl::overlayTransRot90()
{
utils::Dim d = getSrcRectDim();
utils::Whf whf = getSrcWhf();
int tmp = d.x;
d.x = compute(whf.h,
d.y,
d.h);
d.y = tmp;
setSrcRectDim(d);
swapSrcWH();
swapSrcRectWH();
}
/////// MdpCtrl3D //////
inline MdpCtrl3D::MdpCtrl3D() { reset(); }
inline bool MdpCtrl3D::close() {
if (m3DOVInfo.is_3d) {
m3DOVInfo.is_3d = 0;
if(!mdp_wrapper::set3D(mFd.getFD(), m3DOVInfo)) {
ALOGE("MdpCtrl3D close failed set3D with 0");
return false;
}
}
reset();
return true;
}
inline void MdpCtrl3D::reset() {
utils::memset0(m3DOVInfo);
}
inline void MdpCtrl3D::setFd(int fd) {
mFd.copy(fd);
OVASSERT(mFd.valid(), "MdpCtrl3D setFd, FD should be valid");
}
inline void MdpCtrl3D::setWh(const utils::Whf& whf) {
// ignore fmt. Needed for useVirtualFB callflow
m3DOVInfo.width = whf.w;
m3DOVInfo.height = whf.h;
}
inline bool MdpCtrl3D::useVirtualFB() {
if(!m3DOVInfo.is_3d) {
m3DOVInfo.is_3d = 1;
if(!mdp_wrapper::set3D(mFd.getFD(), m3DOVInfo)) {
ALOGE("MdpCtrl3D close failed set3D with 0");
return false;
}
}
return true;
}
/////// MdpData //////
inline MdpData::MdpData() { reset(); }
inline MdpData::~MdpData() { close(); }
inline bool MdpData::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;
}
inline void MdpData::reset() {
overlay::utils::memset0(mOvData);
mOvData.data.memory_id = -1;
}
inline bool MdpData::close() {
if(-1 == mOvData.data.memory_id) return true;
reset();
if(!mFd.close()) {
return false;
}
return true;
}
inline int MdpData::getSrcMemoryId() const { return mOvData.data.memory_id; }
inline void MdpData::setPipeId(int id) { mOvData.id = id; }
inline int MdpData::getPipeId() const { return mOvData.id; }
inline int MdpData::getFd() const { return mFd.getFD(); }
inline bool MdpData::play(int fd, uint32_t offset) {
mOvData.data.memory_id = fd;
mOvData.data.offset = offset;
if(!mdp_wrapper::play(mFd.getFD(), mOvData)){
ALOGE("MdpData failed to play");
dump();
return false;
}
return true;
}
} // overlay
#endif // OVERLAY_MDP_H