Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / opengl / FGrp_GlPlayerImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 /*
19  * @file        FGrp_GlPlayerImpl.cpp
20  * @brief       This is the implementation file for _GlPlayerImpl class.
21  *
22  */
23
24 #include <memory>
25
26 #include <FUiCtrlForm.h>
27 #include <FUiCtrlFrame.h>
28 #include <FBaseSysLog.h>
29 #include <FSysSystemTime.h>
30
31 #include <FGrpGlPlayer.h>
32
33 #include "FGrp_GlPlayerImpl.h"
34
35 namespace Tizen { namespace Graphics { namespace Opengl
36 {
37
38 _GlPlayerImpl::_GlPlayerImpl(void)
39         : __pRenderer(null)
40         , __pTimer(null)
41         , __pTargetControl(null)
42         , __eglDisplay(EGL_NO_DISPLAY)
43         , __eglSurface(EGL_NO_SURFACE)
44         , __eglConfig(null)
45         , __eglContext(EGL_NO_CONTEXT)
46         , __fps(50)
47         , __renderTimeInterval(20)
48         , __eglContextClientVersion(EGL_CONTEXT_CLIENT_VERSION_2_X)
49         , __playerState(PLAYER_STATE_NOT_INITIALIZED)
50 {
51         __eglConfigList[0] = EGL_NONE;
52 }
53
54 _GlPlayerImpl::~_GlPlayerImpl(void)
55 {
56         __DestroyGl();
57
58         if (__pTimer != null)
59         {
60                 __pTimer->Cancel();
61                 delete __pTimer;
62         }
63 }
64
65 bool
66 _GlPlayerImpl::__CheckReadyToStart(void)
67 {
68         return (__pTargetControl == null) ? false : true;
69 }
70
71 bool
72 _GlPlayerImpl::__DestroyGl(void)
73 {
74         if (__eglDisplay == EGL_NO_DISPLAY)
75         {
76                 return false;
77         }
78
79         if (__pRenderer != null)
80         {
81                 __pRenderer->TerminateGl();
82                 __pRenderer = null;
83         }
84
85         eglMakeCurrent(__eglDisplay, null, null, null);
86         if (__eglContext != EGL_NO_CONTEXT)
87         {
88                 eglDestroyContext(__eglDisplay, __eglContext);
89                 __eglContext = EGL_NO_CONTEXT;
90         }
91
92         if (__eglSurface != EGL_NO_SURFACE)
93         {
94                 eglDestroySurface(__eglDisplay, __eglSurface);
95                 __eglSurface = EGL_NO_SURFACE;
96         }
97
98         eglTerminate(__eglDisplay);
99         __eglDisplay = EGL_NO_DISPLAY;
100
101         return true;
102 }
103
104 result
105 _GlPlayerImpl::Construct(EglContextClientVersion version, Tizen::Ui::Control* pControl)
106 {
107         SysTryReturnResult(NID_GRP, version == EGL_CONTEXT_CLIENT_VERSION_1_X ||
108                 version == EGL_CONTEXT_CLIENT_VERSION_2_X, E_INVALID_ARG, "The input client version is invalid");
109
110         Tizen::Ui::Controls::Form* pForm = dynamic_cast<Tizen::Ui::Controls::Form*> (pControl);
111         Tizen::Ui::Controls::Frame* pFrame = dynamic_cast<Tizen::Ui::Controls::Frame*> (pControl);
112         SysTryReturnResult(NID_GRP, pForm != null || pFrame != null,  E_INVALID_ARG,
113                 "The input target pControl is not allowable. Only Form/Frame are acceptable. ");
114         SysTryReturnResult(NID_GRP, __pTargetControl == null,  E_INVALID_OPERATION,
115                 "It is not allowable to call Construct() function, and the target pControl is not replacable.");
116
117         std::auto_ptr<Tizen::Base::Runtime::Timer> timer(new (std::nothrow) Tizen::Base::Runtime::Timer);
118         SysTryReturnResult(NID_GRP, timer.get() != null, E_OUT_OF_MEMORY, "Fail to generate Timer. ");
119         SysTryReturnResult(NID_GRP, timer->Construct(*this) == E_SUCCESS, E_OUT_OF_MEMORY, "Fail to construct Timer. ");
120
121         __eglContextClientVersion = version;
122         __pTargetControl = pControl;
123         __pTimer = timer.release();
124
125         return E_SUCCESS;
126 }
127
128 bool
129 _GlPlayerImpl::IsValid(void) const
130 {
131         return (this && this->__pTimer);
132 }
133
134 result
135 _GlPlayerImpl::Start(void)
136 {
137         EGLint numConfigs;
138         EGLint eglContextList[3] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
139
140         if (__playerState == PLAYER_STATE_START)
141         {
142                 return E_SUCCESS;
143         }
144
145         if (__playerState == PLAYER_STATE_PAUSE)
146         {
147                 SysTryReturnResult(NID_GRP, false, E_INVALID_STATE, "Cannot start player when the player's state is paused.");
148         }
149
150         SysTryReturnResult(NID_GRP, __CheckReadyToStart(), E_INVALID_STATE, "This instance is not ready to start yet.");
151
152         eglBindAPI(EGL_OPENGL_ES_API);
153         if (__eglDisplay != EGL_NO_DISPLAY)
154         {
155                 __DestroyGl();
156         }
157
158         __eglDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
159         SysTryReturnResult(NID_GRP, __eglDisplay != EGL_NO_DISPLAY, E_OPENGL_ERROR, "Fail to find EGL_DEFAULT_DISPLAY device with eglGetDisplay().");
160
161         if (eglInitialize(__eglDisplay, null, null) == EGL_FALSE || eglGetError() != EGL_SUCCESS)
162         {
163                 __DestroyGl();
164                 SysTryReturnResult(NID_GRP, false, E_OPENGL_ERROR, "Fail to initialize egl with eglInitialize().");
165         }
166
167         if (eglChooseConfig(__eglDisplay, __eglConfigList, &__eglConfig, 1, &numConfigs) == EGL_FALSE || eglGetError() != EGL_SUCCESS)
168         {
169                 __DestroyGl();
170                 SysTryReturnResult(NID_GRP, false, E_OPENGL_ERROR, "Fail to choose appropriate egl configurations with eglChooseConfig().");
171         }
172
173         if (numConfigs == 0)
174         {
175                 __DestroyGl();
176                 SysTryReturnResult(NID_GRP, false, E_OPENGL_ERROR, "There is no matching configuration for the given condition.");
177         }
178
179         __eglSurface = eglCreateWindowSurface(__eglDisplay, __eglConfig, (EGLNativeWindowType)__pTargetControl, null);
180         if (__eglSurface == EGL_NO_SURFACE || eglGetError() != EGL_SUCCESS)
181         {
182                 __DestroyGl();
183                 SysTryReturnResult(NID_GRP, false, E_OPENGL_ERROR, "Fail to create window surface with eglCreateWindowSurface().");
184         }
185
186         switch (__eglContextClientVersion)
187         {
188         case EGL_CONTEXT_CLIENT_VERSION_1_X:
189                 eglContextList[1] = 1;
190                 break;
191         case EGL_CONTEXT_CLIENT_VERSION_2_X:
192                 eglContextList[1] = 2;
193                 break;
194         }
195         __eglContext = eglCreateContext(__eglDisplay, __eglConfig, EGL_NO_CONTEXT, eglContextList);
196         if (__eglContext == EGL_NO_CONTEXT || eglGetError() != EGL_SUCCESS)
197         {
198                 __DestroyGl();
199                 SysTryReturnResult(NID_GRP, false, E_OPENGL_ERROR, "Fail to create egl context with eglCreateContext().");
200         }
201
202         if (eglMakeCurrent(__eglDisplay, __eglSurface, __eglSurface, __eglContext) == EGL_FALSE || eglGetError() != EGL_SUCCESS)
203         {
204                 __DestroyGl();
205                 SysTryReturnResult(NID_GRP, false, E_OPENGL_ERROR, "Fail to active the current context with eglMakeCurrent().");
206         }
207
208         if (__fps > 0)
209         {
210                 result r = __pTimer->Start(__renderTimeInterval);
211                 SysTryReturnResult(NID_GRP, r == E_SUCCESS, r, "Fail to resume Timer.");
212         }
213
214         __playerState = PLAYER_STATE_START;
215
216         return E_SUCCESS;
217 }
218
219 result
220 _GlPlayerImpl::Pause(void)
221 {
222         if (__playerState == PLAYER_STATE_PAUSE || __playerState == PLAYER_STATE_STOP)
223         {
224                 return E_SUCCESS;
225         }
226
227         if (__playerState == PLAYER_STATE_NOT_INITIALIZED)
228         {
229                 SysTryReturnResult(NID_GRP, false, E_INVALID_STATE, "Cannot pause player when the player is not started.");
230         }
231
232         if (__pTimer != null)
233         {
234                 result r = __pTimer->Cancel();
235                 SysTryReturnResult(NID_GRP, r == E_SUCCESS, r, "Fail to pause Timer.");
236         }
237
238         if (__pRenderer != null)
239         {
240                 SysTryReturnResult(NID_GRP, __pRenderer->Pause(), E_INVALID_OPERATION, "Fail to perform IGlRenderer::Pause() function .");
241         }
242
243         __playerState = PLAYER_STATE_PAUSE;
244
245         return E_SUCCESS;
246 }
247
248 result
249 _GlPlayerImpl::Resume(void)
250 {
251         if (__playerState == PLAYER_STATE_START)
252         {
253                 return E_SUCCESS;
254         }
255
256         if (__playerState == PLAYER_STATE_NOT_INITIALIZED || __playerState == PLAYER_STATE_STOP)
257         {
258                 SysTryReturnResult(NID_GRP, false, E_INVALID_STATE, "Cannot resume player when the player is not started.");
259         }
260
261         if (__pRenderer != null)
262         {
263                 SysTryReturnResult(NID_GRP, __pRenderer->Resume(), E_INVALID_OPERATION, "Fail to perform IGlRenderer::Resume() function .");
264         }
265         if (__pTimer != null)
266         {
267                 result r = __pTimer->Start(__renderTimeInterval);
268                 SysTryReturnResult(NID_GRP, r == E_SUCCESS, r, "Fail to resume Timer.");
269         }
270
271         __playerState = PLAYER_STATE_START;
272
273         return E_SUCCESS;
274 }
275
276 result
277 _GlPlayerImpl::Stop(void)
278 {
279         if (__playerState == PLAYER_STATE_STOP || __playerState == PLAYER_STATE_NOT_INITIALIZED)
280         {
281                 return E_SUCCESS;
282         }
283
284         if (__playerState == PLAYER_STATE_PAUSE)
285         {
286                 __DestroyGl();
287                 __playerState = PLAYER_STATE_STOP;
288         }
289
290         if (__pTimer != null)
291         {
292                 result r = __pTimer->Cancel();
293                 SysTryReturnResult(NID_GRP, r == E_SUCCESS, r, "Fail to pause Timer.");
294         }
295
296         if (__pRenderer != null)
297         {
298                 SysTryReturnResult(NID_GRP, __pRenderer->Pause(), E_INVALID_OPERATION, "Fail to perform IGlRenderer::Pause() function .");
299         }
300
301         __DestroyGl();
302         __playerState = PLAYER_STATE_STOP;
303
304         return E_SUCCESS;
305 }
306
307 result
308 _GlPlayerImpl::Redraw(void)
309 {
310         SysTryReturnResult(NID_GRP, eglMakeCurrent(__eglDisplay, __eglSurface, __eglSurface, __eglContext) != EGL_FALSE, E_OPENGL_ERROR, "eglMakeCurrent() has been failed.");
311
312         if (__pRenderer != null)
313         {
314                 __pRenderer->Draw();
315                 eglSwapBuffers(__eglDisplay, __eglSurface);
316         }
317
318         return E_SUCCESS;
319 }
320
321 result
322 _GlPlayerImpl::SetFps(int fps)
323 {
324         __fps = fps;
325         if (fps > 0)
326         {
327                 __renderTimeInterval = (int)((float)1000 / (float)fps + 0.5f);
328         }
329         else
330         {
331                 __renderTimeInterval = -1;
332         }
333
334         return E_SUCCESS;
335 }
336
337 result
338 _GlPlayerImpl::SetEglAttributeList(const EGLint* pEglConfigList)
339 {
340         int index = 0;
341
342         SysTryReturnResult(NID_GRP, pEglConfigList != null, E_INVALID_ARG, "Input is invalid EGL attribute list. ");
343
344         while (pEglConfigList[index] != EGL_NONE)
345         {
346                 SysTryReturnResult(NID_GRP, index < 38, E_INVALID_ARG, "Input eglConfigList does not have terminal symbol 'EGL_NONE'. ");
347
348                 __eglConfigList[index] = pEglConfigList[index];
349                 __eglConfigList[index+1] = pEglConfigList[index+1];
350                 index += 2;
351         }
352         __eglConfigList[index] = EGL_NONE;
353
354         return E_SUCCESS;
355 }
356
357 result
358 _GlPlayerImpl::SetEglAttributePreset(EglAttributesPreset preset)
359 {
360         int index = 0;
361
362         switch (preset)
363         {
364         case EGL_ATTRIBUTES_PRESET_RGB565:
365                 __eglConfigList[index++] = EGL_RED_SIZE;
366                 __eglConfigList[index++] = 5;
367                 __eglConfigList[index++] = EGL_GREEN_SIZE;
368                 __eglConfigList[index++] = 6;
369                 __eglConfigList[index++] = EGL_BLUE_SIZE;
370                 __eglConfigList[index++] = 5;
371                 break;
372         case EGL_ATTRIBUTES_PRESET_ARGB8888:
373                 __eglConfigList[index++] = EGL_ALPHA_SIZE;
374                 __eglConfigList[index++] = 8;
375                 __eglConfigList[index++] = EGL_RED_SIZE;
376                 __eglConfigList[index++] = 8;
377                 __eglConfigList[index++] = EGL_GREEN_SIZE;
378                 __eglConfigList[index++] = 8;
379                 __eglConfigList[index++] = EGL_BLUE_SIZE;
380                 __eglConfigList[index++] = 8;
381                 break;
382         case EGL_ATTRIBUTES_PRESET_DONT_CARE:
383                 break;
384         default:
385                 SysTryReturnResult(NID_GRP, false, E_INVALID_ARG, "Input preset is invalid. ");
386                 break;
387         }
388         __eglConfigList[index] = EGL_NONE;
389
390         return E_SUCCESS;
391 }
392
393 result
394 _GlPlayerImpl::SetEglAttribute(EGLint key, EGLint value)
395 {
396         int index = 0;
397
398         if (key != EGL_BUFFER_SIZE && key != EGL_RED_SIZE && key != EGL_GREEN_SIZE && key != EGL_BLUE_SIZE && key != EGL_ALPHA_SIZE &&
399                 key != EGL_CONFIG_CAVEAT && key != EGL_CONFIG_ID && key != EGL_DEPTH_SIZE && key != EGL_LEVEL && key != EGL_NATIVE_RENDERABLE &&
400                 key != EGL_NATIVE_VISUAL_TYPE && key != EGL_SAMPLE_BUFFERS && key != EGL_SAMPLES && key != EGL_STENCIL_SIZE && key != EGL_SURFACE_TYPE &&
401                 key != EGL_TRANSPARENT_TYPE && key != EGL_TRANSPARENT_RED_VALUE && key != EGL_TRANSPARENT_GREEN_VALUE && key != EGL_TRANSPARENT_BLUE_VALUE)
402         {
403                 SysTryReturnResult(NID_GRP, false, E_INVALID_ARG, "Input key is invalid for EGL attributes");
404         }
405
406         while (__eglConfigList[index] != key && __eglConfigList[index] != EGL_NONE)
407         {
408                 index += 2;
409         }
410
411         if (__eglConfigList[index] == EGL_NONE)
412         {
413                 __eglConfigList[index] = key;
414                 __eglConfigList[index+2] = EGL_NONE;
415         }
416         __eglConfigList[index+1] = value;
417
418         return E_SUCCESS;
419 }
420
421 result
422 _GlPlayerImpl::SetIGlRenderer(IGlRenderer* pRenderer)
423 {
424         if (pRenderer != null)
425         {
426                 int x = 0;
427                 int y = 0;
428                 int width = 0;
429                 int height = 0;
430
431                 __pTargetControl->GetBounds(x, y, width, height);
432                 pRenderer->SetTargetControlWidth(width);
433                 pRenderer->SetTargetControlHeight(height);
434
435                 SysTryReturnResult(NID_GRP, pRenderer->InitializeGl(),  E_INVALID_OPERATION, "Fail to InitializeGl() for the given pRenderer. ");
436         }
437         if (__pRenderer != null)
438         {
439                 __pRenderer->TerminateGl();
440         }
441
442         __pRenderer = pRenderer;
443
444         return E_SUCCESS;
445 }
446
447 void
448 _GlPlayerImpl::OnTimerExpired(Tizen::Base::Runtime::Timer& timer)
449 {
450         if (__pTimer == null)
451         {
452                 return;
453         }
454         __pTimer->Start(__renderTimeInterval);
455
456         if (Redraw() != E_SUCCESS)
457         {
458                 SysLog(NID_GRP, "Redraw() in OnTimerExpired() has failed. ");
459         }
460 }
461
462 _GlPlayerImpl*
463 _GlPlayerImpl::GetInstance(GlPlayer& player)
464 {
465         return (&player != null) ? player.__pImpl : null;
466 }
467
468 const _GlPlayerImpl*
469 _GlPlayerImpl::GetInstance(const GlPlayer& player)
470 {
471         return (&player != null) ? player.__pImpl : null;
472 }
473
474 }}} // Tizen::Graphics::Opengl