blob: ed968c1bfd195e93f0a429d5c9d1da3d372ce8d4 [file] [log] [blame]
Naseer Ahmed29a26812012-06-14 00:56:20 -07001/*
2* Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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#include "overlayUtils.h"
31#include "overlayImpl.h"
32#include "overlay.h"
33
34// MDP related FIXME move to state
35#include "overlayMdp.h"
36#include "overlayCtrlData.h"
37#include "overlayRotator.h"
38
39namespace overlay {
40
41Overlay::Overlay(): mOv(0) {
42}
43
44Overlay::~Overlay() {
45 if(mState.state() == utils::OV_CLOSED) return;
46 close();
47 delete mOv;
48 mOv = 0;
49}
50
51bool Overlay::open() {
52 // We need an empty open to just open the bare minimum for business
53 return true;
54}
55
56void Overlay::reset(){
57 if(mOv && !mOv->close()) {
58 ALOGE("%s Overlay failed", __FUNCTION__);
59 }
60
61 delete mOv;
62 mOv = 0;
63}
64
65bool Overlay::close()
66{
67 OVASSERT(mOv,
68 "%s Overlay and Rotator should be init at this point",
69 __FUNCTION__);
70 // FIXME that one needs to move to the state machine class
71 utils::eOverlayState st = mState.state();
72 switch (st) {
73 case utils::OV_CLOSED:
74 // try to close any partially opened items
75 break;
76 case utils::OV_2D_VIDEO_ON_PANEL:
77 case utils::OV_2D_VIDEO_ON_PANEL_TV:
78 case utils::OV_3D_VIDEO_ON_2D_PANEL:
79 case utils::OV_3D_VIDEO_ON_3D_PANEL:
80 case utils::OV_3D_VIDEO_ON_3D_TV:
81 case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
82 case utils::OV_UI_MIRROR:
83 case utils::OV_2D_TRUE_UI_MIRROR:
84 case utils::OV_BYPASS_1_LAYER:
85 case utils::OV_BYPASS_2_LAYER:
86 case utils::OV_BYPASS_3_LAYER:
87 mOv = mState.handleEvent(utils::OV_CLOSED, mOv);
88 this->reset();
89 break;
90 default:
91 OVASSERT(false, "close Unknown state %d", st);
92 return false;
93 }
94 return true;
95}
96
97bool Overlay::commit(utils::eDest dest)
98{
99 OVASSERT(mOv,
100 "%s Overlay and Rotator should be init at this point",
101 __FUNCTION__);
102 // FIXME that one needs to move to the state machine class
103 utils::eOverlayState st = mState.state();
104 switch (st) {
105 case utils::OV_2D_VIDEO_ON_PANEL:
106 case utils::OV_2D_VIDEO_ON_PANEL_TV:
107 case utils::OV_3D_VIDEO_ON_2D_PANEL:
108 case utils::OV_3D_VIDEO_ON_3D_PANEL:
109 case utils::OV_3D_VIDEO_ON_3D_TV:
110 case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
111 case utils::OV_UI_MIRROR:
112 case utils::OV_2D_TRUE_UI_MIRROR:
113 case utils::OV_BYPASS_1_LAYER:
114 case utils::OV_BYPASS_2_LAYER:
115 case utils::OV_BYPASS_3_LAYER:
116 if(!mOv->commit(dest)) {
117 ALOGE("Overlay %s failed", __FUNCTION__);
118 return false;
119 }
120 break;
121 default:
122 OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
123 return false;
124 }
125 return true;
126}
127
128bool Overlay::queueBuffer(uint32_t offset,
129 utils::eDest dest)
130{
131 OVASSERT(mOv,
132 "%s Overlay and Rotator should be init at this point",
133 __FUNCTION__);
134 // FIXME that one needs to move to the state machine class
135 utils::eOverlayState st = mState.state();
136 switch (st) {
137 case utils::OV_2D_VIDEO_ON_PANEL:
138 case utils::OV_2D_VIDEO_ON_PANEL_TV:
139 case utils::OV_3D_VIDEO_ON_2D_PANEL:
140 case utils::OV_3D_VIDEO_ON_3D_PANEL:
141 case utils::OV_3D_VIDEO_ON_3D_TV:
142 case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
143 case utils::OV_UI_MIRROR:
144 case utils::OV_2D_TRUE_UI_MIRROR:
145 case utils::OV_BYPASS_1_LAYER:
146 case utils::OV_BYPASS_2_LAYER:
147 case utils::OV_BYPASS_3_LAYER:
148 if(!mOv->queueBuffer(offset, dest)) {
149 ALOGE("Overlay %s failed", __FUNCTION__);
150 return false;
151 }
152 break;
153 default:
154 OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
155 return false;
156 }
157 return true;
158}
159
160bool Overlay::dequeueBuffer(void*& buf,
161 utils::eDest dest)
162{
163 OVASSERT(mOv,
164 "%s Overlay and Rotator should be init at this point",
165 __FUNCTION__);
166 // FIXME that one needs to move to the state machine class
167 utils::eOverlayState st = mState.state();
168 switch (st) {
169 case utils::OV_2D_VIDEO_ON_PANEL:
170 case utils::OV_2D_VIDEO_ON_PANEL_TV:
171 case utils::OV_3D_VIDEO_ON_2D_PANEL:
172 case utils::OV_3D_VIDEO_ON_3D_PANEL:
173 case utils::OV_3D_VIDEO_ON_3D_TV:
174 case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
175 case utils::OV_UI_MIRROR:
176 case utils::OV_2D_TRUE_UI_MIRROR:
177 case utils::OV_BYPASS_1_LAYER:
178 case utils::OV_BYPASS_2_LAYER:
179 case utils::OV_BYPASS_3_LAYER:
180 if(!mOv->dequeueBuffer(buf, dest)) {
181 ALOGE("Overlay %s failed", __FUNCTION__);
182 return false;
183 }
184 break;
185 default:
186 OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
187 return false;
188 }
189 return true;
190}
191
192bool Overlay::waitForVsync(utils::eDest dest)
193{
194 OVASSERT(mOv,
195 "%s Overlay and Rotator should be init at this point",
196 __FUNCTION__);
197 // FIXME that one needs to move to the state machine class
198 utils::eOverlayState st = mState.state();
199 switch (st) {
200 case utils::OV_2D_VIDEO_ON_PANEL:
201 case utils::OV_2D_VIDEO_ON_PANEL_TV:
202 case utils::OV_3D_VIDEO_ON_2D_PANEL:
203 case utils::OV_3D_VIDEO_ON_3D_PANEL:
204 case utils::OV_3D_VIDEO_ON_3D_TV:
205 case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
206 case utils::OV_UI_MIRROR:
207 case utils::OV_2D_TRUE_UI_MIRROR:
208 case utils::OV_BYPASS_1_LAYER:
209 case utils::OV_BYPASS_2_LAYER:
210 case utils::OV_BYPASS_3_LAYER:
211 if(!mOv->waitForVsync(dest)) {
212 ALOGE("Overlay %s failed", __FUNCTION__);
213 return false;
214 }
215 break;
216 default:
217 OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
218 return false;
219 }
220 return true;
221}
222
223bool Overlay::setCrop(const utils::Dim& d,
224 utils::eDest dest)
225{
226 OVASSERT(mOv,
227 "%s Overlay and Rotator should be init at this point",
228 __FUNCTION__);
229 // FIXME that one needs to move to the state machine class
230 utils::eOverlayState st = mState.state();
231 switch (st) {
232 case utils::OV_2D_VIDEO_ON_PANEL:
233 case utils::OV_2D_VIDEO_ON_PANEL_TV:
234 case utils::OV_3D_VIDEO_ON_2D_PANEL:
235 case utils::OV_3D_VIDEO_ON_3D_PANEL:
236 case utils::OV_3D_VIDEO_ON_3D_TV:
237 case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
238 case utils::OV_UI_MIRROR:
239 case utils::OV_2D_TRUE_UI_MIRROR:
240 case utils::OV_BYPASS_1_LAYER:
241 case utils::OV_BYPASS_2_LAYER:
242 case utils::OV_BYPASS_3_LAYER:
243 if(!mOv->setCrop(d, dest)) {
244 ALOGE("Overlay %s failed", __FUNCTION__);
245 return false;
246 }
247 break;
248 default:
249 OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
250 return false;
251 }
252 return true;
253}
254bool Overlay::setPosition(const utils::Dim& d,
255 utils::eDest dest)
256{
257 OVASSERT(mOv,
258 "%s Overlay and Rotator should be init at this point",
259 __FUNCTION__);
260 // FIXME that one needs to move to the state machine class
261 utils::eOverlayState st = mState.state();
262 switch (st) {
263 case utils::OV_2D_VIDEO_ON_PANEL:
264 case utils::OV_2D_VIDEO_ON_PANEL_TV:
265 case utils::OV_3D_VIDEO_ON_2D_PANEL:
266 case utils::OV_3D_VIDEO_ON_3D_PANEL:
267 case utils::OV_3D_VIDEO_ON_3D_TV:
268 case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
269 case utils::OV_UI_MIRROR:
270 case utils::OV_2D_TRUE_UI_MIRROR:
271 case utils::OV_BYPASS_1_LAYER:
272 case utils::OV_BYPASS_2_LAYER:
273 case utils::OV_BYPASS_3_LAYER:
274 if(!mOv->setPosition(d, dest)) {
275 ALOGE("Overlay %s failed", __FUNCTION__);
276 return false;
277 }
278 break;
279 default:
280 OVASSERT(false, "setPos Unknown state %d", st);
281 return false;
282 }
283 return true;
284}
285bool Overlay::setParameter(const utils::Params& param,
286 utils::eDest dest)
287{
288 OVASSERT(mOv,
289 "%s Overlay and Rotator should be init at this point",
290 __FUNCTION__);
291 // FIXME that one needs to move to the state machine class
292 utils::eOverlayState st = mState.state();
293 switch (st) {
294 case utils::OV_2D_VIDEO_ON_PANEL:
295 case utils::OV_2D_VIDEO_ON_PANEL_TV:
296 case utils::OV_3D_VIDEO_ON_2D_PANEL:
297 case utils::OV_3D_VIDEO_ON_3D_PANEL:
298 case utils::OV_3D_VIDEO_ON_3D_TV:
299 case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
300 case utils::OV_UI_MIRROR:
301 case utils::OV_2D_TRUE_UI_MIRROR:
302 case utils::OV_BYPASS_1_LAYER:
303 case utils::OV_BYPASS_2_LAYER:
304 case utils::OV_BYPASS_3_LAYER:
305 if(!mOv->setParameter(param, dest)) {
306 ALOGE("Overlay %s failed", __FUNCTION__);
307 return false;
308 }
309 break;
310 default:
311 OVASSERT(false, "%s Unknown state %d", __FUNCTION__ , st);
312 return false;
313 }
314 return true;
315}
316bool Overlay::setSource(const utils::PipeArgs args[utils::MAX_PIPES],
317 utils::eDest dest)
318{
319 // FIXME that one needs to move to the state machine class
320 utils::PipeArgs margs[utils::MAX_PIPES] = {
321 args[0], args[1], args[2] };
322 utils::eOverlayState st = mState.state();
323
324 switch (st) {
325 case utils::OV_CLOSED:
326 // if we get setSource when we are closed, then
327 // we will assume tranistion to OV_2D_VIDEO_ON_PANEL
328 // returns overlay
329 mOv = mState.handle_closed(utils::OV_2D_VIDEO_ON_PANEL);
330 if (!mOv) {
331 ALOGE("Overlay %s failed", __FUNCTION__);
332 this->reset(); // cleanup
333 return false;
334 }
335 break;
336 case utils::OV_2D_VIDEO_ON_PANEL:
337 case utils::OV_3D_VIDEO_ON_2D_PANEL:
338 case utils::OV_UI_MIRROR:
339 case utils::OV_BYPASS_1_LAYER:
340 case utils::OV_BYPASS_2_LAYER:
341 case utils::OV_BYPASS_3_LAYER:
342 // no tweaking
343 break;
344 case utils::OV_3D_VIDEO_ON_3D_PANEL:
345 case utils::OV_3D_VIDEO_ON_3D_TV:
346 margs[utils::CHANNEL_1].zorder = utils::ZORDER_1;
347 break;
348 case utils::OV_2D_VIDEO_ON_PANEL_TV:
349 case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
350 // If displaying on both, external VG pipe set to be no wait
351 margs[utils::CHANNEL_1].wait = utils::NO_WAIT;
352 break;
353 case utils::OV_2D_TRUE_UI_MIRROR:
354 // Set zorder -- external VG pipe (video) gets 0, RGB pipe (UI) gets 1
355 margs[utils::CHANNEL_1].zorder = utils::ZORDER_0;
356 margs[utils::CHANNEL_2].zorder = utils::ZORDER_1;
357 // External VG (video) and RGB (UI) pipe set to be no wait
358 margs[utils::CHANNEL_0].wait = utils::WAIT;
359 margs[utils::CHANNEL_1].wait = utils::NO_WAIT;
360 margs[utils::CHANNEL_2].wait = utils::NO_WAIT;
361 break;
362 default:
363 OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
364 return false;
365 }
366
367 if (!mOv->setSource(margs, dest)) {
368 ALOGE("Overlay %s failed", __FUNCTION__);
369 return false;
370 }
371
372 return true;
373}
374void Overlay::setMemoryId(int id, utils::eDest dest)
375{
376 OVASSERT(mOv,
377 "%s Overlay and Rotator should be init at this point",
378 __FUNCTION__);
379 // FIXME that one needs to move to the state machine class
380 utils::eOverlayState st = mState.state();
381 switch (st) {
382 case utils::OV_2D_VIDEO_ON_PANEL:
383 case utils::OV_2D_VIDEO_ON_PANEL_TV:
384 case utils::OV_3D_VIDEO_ON_2D_PANEL:
385 case utils::OV_3D_VIDEO_ON_3D_PANEL:
386 case utils::OV_3D_VIDEO_ON_3D_TV:
387 case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
388 case utils::OV_UI_MIRROR:
389 case utils::OV_2D_TRUE_UI_MIRROR:
390 case utils::OV_BYPASS_1_LAYER:
391 case utils::OV_BYPASS_2_LAYER:
392 case utils::OV_BYPASS_3_LAYER:
393 mOv->setMemoryId(id, dest);
394 break;
395 default:
396 OVASSERT(false, "setMemId Unknown state %d", st);
397 }
398}
399
400
401void Overlay::dump() const
402{
403 OVASSERT(mOv,
404 "%s Overlay and Rotator should be init at this point",
405 __FUNCTION__);
406 // FIXME dump tate object, factory
407 ALOGE("== Dump Overlay start ==");
408 mState.dump();
409 mOv->dump();
410 ALOGE("== Dump Overlay end ==");
411}
412
413void Overlay::setState(utils::eOverlayState s) {
414 mOv = mState.handleEvent(s, mOv);
415}
416
417utils::eOverlayState Overlay::getState() const {
418 return mState.state();
419}
420
421Overlay *Overlay::sInstance = 0;
422
423Overlay* Overlay::getInstance() {
424 if(sInstance == NULL)
425 sInstance = new Overlay();
426 return sInstance;
427}
428
429/**** NullPipe ****/
430
431bool NullPipe::open(RotatorBase*) {
432 ALOGE_IF(DEBUG_OVERLAY, "NullPipe open");
433 return true;
434}
435bool NullPipe::close() { return true; }
436bool NullPipe::commit() { return true; }
437bool NullPipe::start(const utils::PipeArgs&) { return true; }
438bool NullPipe::setCrop(const utils::Dim&) { return true; }
439bool NullPipe::setPosition(const utils::Dim&) { return true; }
440bool NullPipe::setParameter(const utils::Params&) { return true; }
441bool NullPipe::setSource(const utils::PipeArgs&) { return true; }
442bool NullPipe::queueBuffer(uint32_t offset) { return true; }
443bool NullPipe::dequeueBuffer(void*&) { return true; }
444bool NullPipe::waitForVsync() { return true; }
445void NullPipe::setMemoryId(int) {}
446// NullPipe will return by val here as opposed to other Pipes.
447utils::PipeArgs NullPipe::getArgs() const { return utils::PipeArgs(); }
448utils::eOverlayPipeType NullPipe::getOvPipeType() const {
449 return utils::OV_PIPE_TYPE_NULL;
450}
451void NullPipe::dump() const {
452 ALOGE("== NullPipe (null) start/end ==");
453}
454
455} // overlay