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 
39 namespace 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 */
47 struct RotMem {
48     // Max rotator buffers
49     enum { ROT_NUM_BUFS = 2 };
50     RotMem();
51     ~RotMem();
52     bool close();
validRotMem53     bool valid() { return mem.valid(); }
sizeRotMem54     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 
66 class Rotator
67 {
68 public:
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;
setCurrBufReleaseFd(const int & fence)100     inline void setCurrBufReleaseFd(const int& fence) {
101         mMem.setCurrBufReleaseFd(fence);
102     }
setPrevBufReleaseFd(const int & fence)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 
115 protected:
116     /* Rotator memory manager */
117     RotMem mMem;
118     Rotator();
119     static uint32_t calcOutputBufSize(const utils::Whf& destWhf);
120 
121 private:
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 * */
132 class MdpRot : public Rotator {
133 public:
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 
154 private:
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 +* */
204 class MdssRot : public Rotator {
205 public:
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 
226 private:
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
287 class RotMgr {
288 public:
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
markUnusedTop(const uint32_t & count)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();
getNumActiveSessions()306     int getNumActiveSessions() { return mUseCount; }
307 
308     static RotMgr *getInstance();
309 
310 private:
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