/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (c) 2010-2013, The Linux Foundation. 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"
#include "qdMetaData.h"
#ifdef USES_POST_PROCESSING
#include "lib-postproc.h"
#endif
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();
/* 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();
/* Sets the source total width, height, format */
void setSource(const utils::PipeArgs& pargs);
/*
* Sets ROI, the unpadded region, for source buffer.
* Dim - ROI dimensions.
*/
void setCrop(const utils::Dim& d);
void setTransform(const utils::eTransform& orient);
/* given a dim and w/h, set overlay dim */
void setPosition(const utils::Dim& dim);
/* using user_data, sets/unsets roationvalue in mdp flags */
void setRotationFlags();
/* Performs downscale calculations */
void setDownscale(int dscale_factor);
/* Update the src format with rotator's dest*/
void updateSrcFormat(const uint32_t& rotDstFormat);
/* dump state of the object */
void dump() const;
/* Return the dump in the specified buffer */
void getDump(char *buf, size_t len);
/* returns session id */
int getPipeId() const;
/* returns the fd associated to ctrl*/
int getFd() const;
/* returns a copy ro dst rect dim */
utils::Dim getDstRectDim() const;
/* returns a copy to src rect dim */
utils::Dim getSrcRectDim() const;
/* setVisualParam */
bool setVisualParams(const MetaData_t& data);
void forceSet();
private:
/* Perform transformation calculations */
void doTransform();
void doDownscale();
/* get orient / user_data[0] */
int getOrient() const;
/* 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);
/* return a copy of src whf*/
utils::Whf getSrcWhf() const;
/* set plane alpha */
void setPlaneAlpha(int planeAlpha);
/* set blending method */
void setBlending(overlay::utils::eBlending blending);
/* set src whf */
void setSrcWhf(const utils::Whf& whf);
/* set src/dst rect dim */
void setSrcRectDim(const utils::Dim d);
void setDstRectDim(const utils::Dim d);
/* 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();
utils::eTransform mOrientation; //Holds requested orientation
/* last good known ov info */
mdp_overlay mLkgo;
/* Actual overlay mdp structure */
mdp_overlay mOVInfo;
/* FD for the mdp fbnum */
OvFD mFd;
int mDownscale;
bool mForceSet;
#ifdef USES_POST_PROCESSING
/* PP Compute Params */
struct compute_params mParams;
/* indicate if PP params have been changed */
bool mPPChanged;
#endif
};
/* 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;
/* Return the dump in the specified buffer */
void getDump(char *buf, size_t len);
private:
/* actual overlay mdp data */
msmfb_overlay_data mOvData;
/* fd to mdp fbnum */
OvFD mFd;
};
//--------------Inlines---------------------------------
///// 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 void MdpCtrl::setDownscale(int dscale) {
mDownscale = dscale;
}
inline void MdpCtrl::setPlaneAlpha(int planeAlpha) {
mOVInfo.alpha = planeAlpha;
}
inline void MdpCtrl::setBlending(overlay::utils::eBlending blending) {
switch((int) blending) {
case utils::OVERLAY_BLENDING_OPAQUE:
mOVInfo.blend_op = BLEND_OP_OPAQUE;
break;
case utils::OVERLAY_BLENDING_PREMULT:
mOVInfo.blend_op = BLEND_OP_PREMULTIPLIED;
break;
case utils::OVERLAY_BLENDING_COVERAGE:
default:
mOVInfo.blend_op = BLEND_OP_COVERAGE;
}
}
inline bool MdpCtrl::ovChanged() const {
#ifdef USES_POST_PROCESSING
// Some pp params are stored as pointer address,
// so can't compare their content directly.
if (mPPChanged) {
return true;
}
#endif
// 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;
}
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;
}
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)
mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
}
inline void MdpCtrl::forceSet() {
mForceSet = true;
}
/////// 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() {
reset();
return mFd.close();
}
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