1/*
2* Copyright (c) 2011,2013 The Linux Foundation. All rights reserved.
3*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions are
6* met:
7*    * Redistributions of source code must retain the above copyright
8*      notice, this list of conditions and the following disclaimer.
9*    * Redistributions in binary form must reproduce the above
10*      copyright notice, this list of conditions and the following
11*      disclaimer in the documentation and/or other materials provided
12*      with the distribution.
13*    * Neither the name of The Linux Foundation. nor the names of its
14*      contributors may be used to endorse or promote products derived
15*      from this software without specific prior written permission.
16*
17* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30#ifndef OVERlAY_ROTATOR_H
31#define OVERlAY_ROTATOR_H
32
33#include <stdlib.h>
34
35#include "mdpWrapper.h"
36#include "overlayUtils.h"
37#include "overlayMem.h"
38
39namespace overlay {
40
41/*
42   Manages the case where new rotator memory needs to be
43   allocated, before previous is freed, due to resolution change etc. If we make
44   rotator memory to be always max size, irrespctive of source resolution then
45   we don't need this RotMem wrapper. The inner class is sufficient.
46*/
47struct RotMem {
48    // Max rotator buffers
49    enum { ROT_NUM_BUFS = 2 };
50    RotMem();
51    ~RotMem();
52    bool close();
53    bool valid() { return mem.valid(); }
54    uint32_t size() const { return mem.bufSz(); }
55    void setCurrBufReleaseFd(const int& fence);
56    void setPrevBufReleaseFd(const int& fence);
57
58    // rotator data info dst offset
59    uint32_t mRotOffset[ROT_NUM_BUFS];
60    int mRelFence[ROT_NUM_BUFS];
61    // current slot being used
62    uint32_t mCurrIndex;
63    OvMem mem;
64};
65
66class Rotator
67{
68public:
69    enum { TYPE_MDP, TYPE_MDSS };
70    virtual ~Rotator();
71    virtual void setSource(const utils::Whf& wfh) = 0;
72    virtual void setCrop(const utils::Dim& crop) = 0;
73    virtual void setFlags(const utils::eMdpFlags& flags) = 0;
74    virtual void setTransform(const utils::eTransform& rot) = 0;
75    virtual bool commit() = 0;
76    /* return true if the current rotator state is cached */
77    virtual bool isRotCached(int fd, uint32_t offset) const;
78    /* return true if current rotator config is same as the last round*/
79    virtual bool rotConfChanged() const = 0;
80    /* return true if the current rotator input buffer fd and offset
81     * are same as the last round */
82    virtual bool rotDataChanged(int fd, uint32_t offset) const;
83    virtual void setDownscale(int ds) = 0;
84    /* returns the src buffer of the rotator for the previous/current round,
85     * depending on when it is called(before/after the queuebuffer)*/
86    virtual int getSrcMemId() const = 0;
87    //Mem id and offset should be retrieved only after rotator kickoff
88    virtual int getDstMemId() const = 0;
89    virtual uint32_t getSrcOffset() const = 0;
90    virtual uint32_t getDstOffset() const = 0;
91    //Destination width, height, format, position should be retrieved only after
92    //rotator configuration is committed via commit API
93    virtual uint32_t getDstFormat() const = 0;
94    virtual utils::Whf getDstWhf() const = 0;
95    virtual utils::Dim getDstDimensions() const = 0;
96    virtual uint32_t getSessId() const = 0;
97    virtual bool queueBuffer(int fd, uint32_t offset) = 0;
98    virtual void dump() const = 0;
99    virtual void getDump(char *buf, size_t len) const = 0;
100    inline void setCurrBufReleaseFd(const int& fence) {
101        mMem.setCurrBufReleaseFd(fence);
102    }
103    inline void setPrevBufReleaseFd(const int& fence) {
104        mMem.setPrevBufReleaseFd(fence);
105    }
106    static Rotator *getRotator();
107    /* Returns downscale by successfully applying constraints
108     * Returns 0 if target doesnt support rotator downscaling
109     * or if any of the constraints are not met
110     */
111    static int getDownscaleFactor(const int& srcW, const int& srcH,
112            const int& dstW, const int& dstH, const uint32_t& mdpFormat,
113            const bool& isInterlaced);
114
115protected:
116    /* Rotator memory manager */
117    RotMem mMem;
118    Rotator();
119    static uint32_t calcOutputBufSize(const utils::Whf& destWhf);
120
121private:
122    bool mRotCacheDisabled;
123    /*Returns rotator h/w type */
124    static int getRotatorHwType();
125    friend class RotMgr;
126};
127
128/*
129* MDP rot holds MDP's rotation related structures.
130*
131* */
132class MdpRot : public Rotator {
133public:
134    virtual ~MdpRot();
135    virtual void setSource(const utils::Whf& wfh);
136    virtual void setCrop(const utils::Dim& crop);
137    virtual void setFlags(const utils::eMdpFlags& flags);
138    virtual void setTransform(const utils::eTransform& rot);
139    virtual bool commit();
140    virtual bool rotConfChanged() const;
141    virtual void setDownscale(int ds);
142    virtual int getSrcMemId() const;
143    virtual int getDstMemId() const;
144    virtual uint32_t getSrcOffset() const;
145    virtual uint32_t getDstOffset() const;
146    virtual uint32_t getDstFormat() const;
147    virtual utils::Whf getDstWhf() const;
148    virtual utils::Dim getDstDimensions() const;
149    virtual uint32_t getSessId() const;
150    virtual bool queueBuffer(int fd, uint32_t offset);
151    virtual void dump() const;
152    virtual void getDump(char *buf, size_t len) const;
153
154private:
155    explicit MdpRot();
156    bool init();
157    bool close();
158    void setRotations(uint32_t r);
159    bool enabled () const;
160    /* remap rot buffers */
161    bool remap(uint32_t numbufs);
162    bool open_i(uint32_t numbufs, uint32_t bufsz);
163    /* Deferred transform calculations */
164    void doTransform();
165    /* reset underlying data, basically memset 0 */
166    void reset();
167    /* save mRotImgInfo to be last known good config*/
168    void save();
169    /* Calculates the rotator's o/p buffer size post the transform calcs and
170     * knowing the o/p format depending on whether fastYuv is enabled or not */
171    uint32_t calcOutputBufSize();
172
173    /* Applies downscale by taking areas
174     * Returns a log(downscale)
175     * Constraints applied:
176     * - downscale should be a power of 2
177     * - Max downscale is 1/8
178     */
179    static int getDownscaleFactor(const int& srcW, const int& srcH,
180            const int& dstW, const int& dstH, const uint32_t& mdpFormat,
181            const bool& isInterlaced);
182
183    /* rot info*/
184    msm_rotator_img_info mRotImgInfo;
185    /* Last saved rot info*/
186    msm_rotator_img_info mLSRotImgInfo;
187    /* rot data */
188    msm_rotator_data_info mRotDataInfo;
189    /* Orientation */
190    utils::eTransform mOrientation;
191    /* rotator fd */
192    OvFD mFd;
193
194    friend Rotator* Rotator::getRotator();
195    friend int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
196            const int& dstW, const int& dstH, const uint32_t& mdpFormat,
197            const bool& isInterlaced);
198};
199
200/*
201+* MDSS Rot holds MDSS's rotation related structures.
202+*
203+* */
204class MdssRot : public Rotator {
205public:
206    virtual ~MdssRot();
207    virtual void setSource(const utils::Whf& wfh);
208    virtual void setCrop(const utils::Dim& crop);
209    virtual void setFlags(const utils::eMdpFlags& flags);
210    virtual void setTransform(const utils::eTransform& rot);
211    virtual bool commit();
212    virtual bool rotConfChanged() const;
213    virtual void setDownscale(int ds);
214    virtual int getSrcMemId() const;
215    virtual int getDstMemId() const;
216    virtual uint32_t getSrcOffset() const;
217    virtual uint32_t getDstOffset() const;
218    virtual uint32_t getDstFormat() const;
219    virtual utils::Whf getDstWhf() const;
220    virtual utils::Dim getDstDimensions() const;
221    virtual uint32_t getSessId() const;
222    virtual bool queueBuffer(int fd, uint32_t offset);
223    virtual void dump() const;
224    virtual void getDump(char *buf, size_t len) const;
225
226private:
227    explicit MdssRot();
228    bool init();
229    bool close();
230    void setRotations(uint32_t r);
231    bool enabled () const;
232    /* remap rot buffers */
233    bool remap(uint32_t numbufs);
234    bool open_i(uint32_t numbufs, uint32_t bufsz);
235    /* Deferred transform calculations */
236    void doTransform();
237    /* reset underlying data, basically memset 0 */
238    void reset();
239    /* save mRotInfo to be last known good config*/
240    void save();
241    /* Calculates the rotator's o/p buffer size post the transform calcs and
242     * knowing the o/p format depending on whether fastYuv is enabled or not */
243    uint32_t calcOutputBufSize();
244    // Calculate the compressed o/p buffer size for BWC
245    uint32_t calcCompressedBufSize(const utils::Whf& destWhf);
246
247     /* Caller's responsibility to swap srcW, srcH if there is a 90 transform
248      * Returns actual downscale (not a log value)
249      * Constraints applied:
250      * - downscale should be a power of 2
251      * - Max downscale is 1/32
252      * - Equal downscale is applied in both directions
253      * - {srcW, srcH} mod downscale = 0
254      * - Interlaced content is not supported
255      */
256    static int getDownscaleFactor(const int& srcW, const int& srcH,
257            const int& dstW, const int& dstH, const uint32_t& mdpFormat,
258            const bool& isInterlaced);
259
260    static utils::Dim getFormatAdjustedCrop(const utils::Dim& crop,
261            const uint32_t& mdpFormat, const bool& isInterlaced);
262
263    static utils::Dim getDownscaleAdjustedCrop(const utils::Dim& crop,
264            const uint32_t& downscale);
265
266    /* MdssRot info structure */
267    mdp_overlay mRotInfo;
268    /* Last saved MdssRot info structure*/
269    mdp_overlay mLSRotInfo;
270    /* MdssRot data structure */
271    msmfb_overlay_data mRotData;
272    /* Orientation */
273    utils::eTransform mOrientation;
274    /* rotator fd */
275    OvFD mFd;
276    /* Enable/Disable Mdss Rot*/
277    bool mEnabled;
278    int mDownscale;
279
280    friend Rotator* Rotator::getRotator();
281    friend int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
282            const int& dstW, const int& dstH, const uint32_t& mdpFormat,
283            const bool& isInterlaced);
284};
285
286// Holder of rotator objects. Manages lifetimes
287class RotMgr {
288public:
289    //Virtually we can support as many rotator sessions as possible, However
290    // more number of rotator sessions leads to performance issues, so
291    // restricting the max rotator session to 4
292    enum { MAX_ROT_SESS = 4 };
293
294    ~RotMgr();
295    void configBegin();
296    void configDone();
297    overlay::Rotator *getNext();
298    void clear(); //Removes all instances
299    //Resets the usage of top count objects, making them available for reuse
300    void markUnusedTop(const uint32_t& count) { mUseCount -= count; }
301    /* Returns rot dump.
302     * Expects a NULL terminated buffer of big enough size.
303     */
304    void getDump(char *buf, size_t len);
305    int getRotDevFd();
306    int getNumActiveSessions() { return mUseCount; }
307
308    static RotMgr *getInstance();
309
310private:
311    RotMgr();
312    static RotMgr *sRotMgr;
313
314    overlay::Rotator *mRot[MAX_ROT_SESS];
315    uint32_t mUseCount;
316    int mRotDevFd;
317};
318
319
320} // overlay
321
322#endif // OVERlAY_ROTATOR_H
323