blob: 6f84d0745d4d105430bcf2687651d662b09f837e [file] [log] [blame]
Naseer Ahmed29a26812012-06-14 00:56:20 -07001/*
2* Copyright (C) 2008 The Android Open Source Project
3* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
4*
5* Licensed under the Apache License, Version 2.0 (the "License");
6* you may not use this file except in compliance with the License.
7* You may obtain a copy of the License at
8*
9* http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing, software
12* distributed under the License is distributed on an "AS IS" BASIS,
13* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14* See the License for the specific language governing permissions and
15* limitations under the License.
16*/
17
18#include <cutils/properties.h>
19#include "overlayCtrlData.h"
20#include "fb_priv.h"
21
22namespace overlay{
23
24bool Ctrl::open(uint32_t fbnum,
25 RotatorBase* rot) {
26 // MDP/FD open
27 if(!mMdp.open(fbnum)) {
28 ALOGE("Ctrl failed to open fbnum=%d", fbnum);
29 return false;
30 }
31
32 if(!getScreenInfo(mInfo)) {
33 ALOGE("Ctrl failed to getScreenInfo");
34 return false;
35 }
36
37 OVASSERT(rot, "rot is null");
38 mRot = rot;
39 // rot should be already opened
40
41 return true;
42}
43
44bool Ctrl::start(const utils::PipeArgs& args)
45{
46 int colorFormat = utils::getColorFormat(args.whf.format);
47 utils::eMdpFlags flags = args.mdpFlags;
48
49 //XXX: Support for interlaced content
50 if (0) {
51
52 setMdpFlags(flags, utils::OV_MDP_DEINTERLACE);
53
54 // Get the actual format
55 colorFormat = args.whf.format ^ HAL_PIXEL_FORMAT_INTERLACE;
56 }
57 utils::Whf hwwhf(args.whf);
58 int fmt = utils::getMdpFormat(colorFormat);
59 // FIXME format should probably be int and not uint
60 if (fmt < 0) {
61 ALOGE("Ctrl failed getMdpFormat unsopported "
62 "colorFormat=%d format=%d flags=%d",
63 colorFormat, fmt, flags);
64 return false;
65 }
66 hwwhf.format = fmt;
67
68 // devices should be already opened
69 // (by calling open earlier in the flow)
70
71 const utils::PipeArgs newargs(flags, // mdp flags
72 args.orientation, // trans
73 hwwhf,
74 args.wait,
75 args.zorder,
76 args.isFg,
77 args.rotFlags);
78 if (!setInfo(newargs)) {
79 ALOGE("Ctrl failed to setInfo mdpflags=%d wait=%d zorder=%d",
80 newargs.mdpFlags, newargs.wait, newargs.zorder);
81 hwwhf.dump();
82 return false;
83 }
84
85 // FIXME, can we remove that and have it in
86 // setSource only when source changed?
87 if(!mRot->start(newargs)) {
88 ALOGE("Ctrl failed to start Rotation session");
89 return false;
90 }
91
92 // if geom is different, we need to prepare a new rot buffers.
93 // remap on demand when the current orientation is 90,180, etc.
94 // and the prev orientation was 0. It means we go from orient
95 if(!mRot->remap(utils::ROT_NUM_BUFS, newargs)) {
96 ALOGE("%s Error in remapping", __FUNCTION__);
97 }
98
99 if(!mMdp.set()) {
100 ALOGE("Ctrl start failed set overlay");
101 return false;
102 }
103
104 // cache the src to be the current mCrop vals
105 mCrop.w = hwwhf.w;
106 mCrop.h = hwwhf.h;
107
108 return true;
109}
110
111inline void Ctrl::updateSource(RotatorBase* r,
112 const utils::PipeArgs& args,
113 utils::ScreenInfo& info)
114{
115 mMdp.updateSource(r, args, info);
116}
117
118bool Ctrl::setSource(const utils::PipeArgs& args)
119{
120 mMdp.setWait(args.wait);
121
122 utils::PipeArgs newargs(args);
123 utils::Whf whf(args.whf);
124 // check geom change
125 if(mOvBufInfo != whf) {
126 // whf.format is given as HAL, that is why it is
127 // needed to be MDP fmt.
128 whf.format = utils::getColorFormat(whf.format);
129 int fmt = utils::getMdpFormat(whf.format);
130 OVASSERT(-1 != fmt, "Ctrl setSource format is -1");
131 whf.format = fmt;
132 newargs.whf = whf;
133 updateSource(mRot, newargs, mInfo);
134 mMdp.setUserData(0);
135 if(!mRot->start(newargs)) {
136 ALOGE("%s failed start rot", __FUNCTION__);
137 return false;
138 }
139
140 // if geom is different, we need to prepare a new rot buffers.
141 // remap on demand when the current orientation is 90,180, etc.
142 // and the prev orientation was 0. It means we go from orient
143 if(!mRot->remap(utils::ROT_NUM_BUFS, newargs)) {
144 ALOGE("%s Error in remapping", __FUNCTION__);
145 }
146 }
147
148 // needed for setSource
149 mOrient = args.orientation;
150
151 // cache last whf from gralloc hnd
152 mOvBufInfo = args.whf;
153
154 // orign impl is returning false here
155 // because they will close the overlay and reopen it.
156 // New design would not do that.
157 return true;
158}
159
160bool Ctrl::setPosition(const utils::Dim& dim)
161{
162 if(!dim.check(mInfo.mFBWidth, mInfo.mFBHeight)) {
163 ALOGE("Ctrl setPosition error in dim");
164 dim.dump();
165 return false;
166 }
167
168 if(!mMdp.setPosition(dim, mInfo.mFBWidth, mInfo.mFBHeight)) {
169 ALOGE("Ctrl failed MDP setPosition");
170 return false;
171 }
172 return true;
173}
174
175bool Ctrl::setParameter(const utils::Params& p)
176{
177 if (utils::OVERLAY_TRANSFORM == p.param &&
178 p.value == mMdp.getUserData()) {
179 // nothing to do here
180 return true;
181 }
182
183 utils::eTransform trns = static_cast<utils::eTransform>(p.value);
184 switch (p.param) {
185 case utils::OVERLAY_DITHER:
186 // nothing here today
187 ALOGE("Ctrl setParameter OVERLAY_DITHER not impl");
188 return true;
189 case utils::OVERLAY_TRANSFORM:
190 if(!mRot->overlayTransform(mMdp, trns)) {
191 ALOGE("Ctrl setParameter failed Rot overlayTransform");
192 return false;
193 }
194 break;
195 default:
196 ALOGE("Ctrl setParameter unknown param %d", p.param);
197 return false;
198 }
199 return true;
200}
201
202bool Ctrl::setCrop(const utils::Dim& d)
203{
204 // FIXME check channel validity
205 if(!mMdp.setCrop(d)) {
206 ALOGE("Data setCrop failed in MDP setCrop");
207 return false;
208 }
209 mCrop = d;
210 return true;
211}
212
213utils::Dim Ctrl::getAspectRatio(const utils::Whf& whf) const
214{
215 utils::Whf inWhf(whf.w, whf.h, mMdp.getSrcWhf().format);
216 utils::Whf tmpwhf(inWhf);
217 uint32_t fbWidth = mInfo.mFBWidth;
218 uint32_t fbHeight = mInfo.mFBHeight;
219
220 /* Calculate the width and height if it is YUV TILE format*/
221 if (inWhf.format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
222 tmpwhf.w = whf.w - (utils::alignup(whf.w, 64) - whf.w);
223 tmpwhf.h = whf.h - (utils::alignup(whf.h, 32) - whf.h);
224 }
225 if (inWhf.w * fbHeight > fbWidth * inWhf.h) {
226 inWhf.h = fbWidth * inWhf.h / inWhf.w;
227 utils::even_out(inWhf.h);
228 inWhf.w = fbWidth;
229 } else if (inWhf.w * fbHeight < fbWidth * inWhf.h) {
230 inWhf.w = fbHeight * inWhf.w / inWhf.h;
231 utils::even_out(inWhf.w);
232 inWhf.h = fbHeight;
233 } else {
234 inWhf.w = fbWidth;
235 inWhf.h = fbHeight;
236 }
237 /* Scaling of upto a max of 8 times supported */
238 if (inWhf.w > (tmpwhf.w * utils::HW_OV_MAGNIFICATION_LIMIT)){
239 inWhf.w = utils::HW_OV_MAGNIFICATION_LIMIT * tmpwhf.w;
240 }
241 if(inWhf.h > (tmpwhf.h * utils::HW_OV_MAGNIFICATION_LIMIT)) {
242 inWhf.h = utils::HW_OV_MAGNIFICATION_LIMIT * tmpwhf.h;
243 }
244 if (inWhf.w > fbWidth) inWhf.w = fbWidth;
245 if (inWhf.h > fbHeight) inWhf.h = fbHeight;
246
247 char value[PROPERTY_VALUE_MAX];
248 property_get("hw.actionsafe.width", value, "0");
249 float asWidth = atof(value);
250 property_get("hw.actionsafe.height", value, "0");
251 float asHeight = atof(value);
252 inWhf.w = inWhf.w * (1.0f - asWidth / 100.0f);
253 inWhf.h = inWhf.h * (1.0f - asHeight / 100.0f);
254
255 uint32_t x = (fbWidth - inWhf.w) / 2.0;
256 uint32_t y = (fbHeight - inWhf.h) / 2.0;
257 return utils::Dim(x, y, inWhf.w, inWhf.h);
258}
259
260utils::FrameBufferInfo* utils::FrameBufferInfo::sFBInfoInstance = 0;
261
262// This function gets the destination position for external display
263// based on the position and aspect ratio of the primary
264utils::Dim Ctrl::getAspectRatio(const utils::Dim& dim) const {
265 float priWidth = utils::FrameBufferInfo::getInstance()->getWidth();
266 float priHeight = utils::FrameBufferInfo::getInstance()->getHeight();
267 float fbWidth = mInfo.mFBWidth;
268 float fbHeight = mInfo.mFBHeight;
269 float wRatio = 1.0;
270 float hRatio = 1.0;
271 float xRatio = 1.0;
272 float yRatio = 1.0;
273 utils::Dim inDim(dim);
274
275 int xPos = 0;
276 int yPos = 0;
277 int tmp = 0;
278 utils::Dim tmpDim;
279 switch(inDim.o) {
280 case MDP_ROT_NOP:
281 case MDP_ROT_180:
282 {
283 utils::Whf whf((uint32_t) priWidth, (uint32_t) priHeight, 0);
284 tmpDim = getAspectRatio(whf);
285 xPos = tmpDim.x;
286 yPos = tmpDim.y;
287 fbWidth = tmpDim.w;
288 fbHeight = tmpDim.h;
289
290 if (inDim.o == MDP_ROT_180) {
291 inDim.x = priWidth - (inDim.x + inDim.w);
292 inDim.y = priHeight - (inDim.y + inDim.h);
293 }
294 break;
295 }
296 case MDP_ROT_90:
297 case MDP_ROT_270:
298 {
299 if(inDim.o == MDP_ROT_90) {
300 tmp = inDim.y;
301 inDim.y = priWidth - (inDim.x + inDim.w);
302 inDim.x = tmp;
303 }
304 else if (inDim.o == MDP_ROT_270) {
305 tmp = inDim.x;
306 inDim.x = priHeight - (inDim.y + inDim.h);
307 inDim.y = tmp;
308 }
309
310 // Swap the destination width/height
311 utils::swapWidthHeight(inDim.w, inDim.h);
312 // Swap width/height for primary
313 utils::swapWidthHeight(priWidth, priHeight);
314 utils::Whf whf((uint32_t) priWidth, (uint32_t) priHeight, 0);
315 tmpDim = getAspectRatio(whf);
316 xPos = tmpDim.x;
317 yPos = tmpDim.y;
318 fbWidth = tmpDim.w;
319 fbHeight = tmpDim.h;
320 break;
321 }
322 default:
323 ALOGE("%s: Unknown Orientation", __FUNCTION__);
324 break;
325 }
326
327 // Calculate the position
328 xRatio = inDim.x/priWidth;
329 yRatio = inDim.y/priHeight;
330 wRatio = inDim.w/priWidth;
331 hRatio = inDim.h/priHeight;
332
333 return utils::Dim((xRatio * fbWidth) + xPos, // x
334 (yRatio * fbHeight) + yPos, // y
335 (wRatio * fbWidth), // width
336 (hRatio * fbHeight), // height
337 inDim.o); // orientation
338}
339
340void Ctrl::dump() const {
341 ALOGE("== Dump Ctrl start ==");
342 ALOGE("orient=%d", mOrient);
343 mInfo.dump("mInfo");
344 mMdp.dump();
345 mRot->dump();
346 ALOGE("== Dump Ctrl end ==");
347}
348
349} // overlay