/*
* 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 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 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
