2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
9 // http://floralicense.org/license/
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.
18 * @file FUiEffects_EffectImpl.cpp
19 * @brief This is the source file for the _EffectImpl class
22 #include "FUiEffects_EffectImpl.h"
30 #include <FBaseString.h>
31 #include <FBaseColIList.h>
32 #include <FBaseSysLog.h>
33 #include <FBaseErrors.h>
34 #include <FUiTouchEventInfo.h>
36 #include <FUiEffectsEffect.h>
37 #include <FUiEffectsEffectTouchInfo.h>
38 #include <FUiEffectsIEffectResourceProvider.h>
39 #include <FUiEffectsIEffectEventListener.h>
40 #include <FUiEffectsEffectManager.h>
41 #include <FUi_CoordinateSystemUtils.h>
42 #include <FUiControl.h>
44 #include "FUiEffects_EffectManagerImpl.h"
45 #include <FUiEffects_LoggingProfiler.h>
46 #include "FUiEffects_EffectErrorMessages.h"
47 #include <FUiEffects_RuntimeIEffectModelListener.h>
48 #include <FUiEffects_ParserEffectParser.h>
50 #include "FUiEffects_RuntimeRenderDataScene.h"
52 using namespace Tizen::Ui::Controls;
53 using namespace Tizen::Base::Runtime;
54 using namespace Tizen::Ui;
55 using namespace Tizen::Base;
56 using namespace Tizen::Graphics;
57 using namespace Tizen::Base::Collection;
59 using namespace Tizen::Ui::Effects::_Runtime;
60 using namespace Tizen::Ui::Effects::_Renderer;
61 using namespace Tizen::Ui::Effects::_Parser;
62 using namespace Tizen::Ui::Effects;
63 using namespace Tizen::Ui::Effects::_Utils;
66 namespace Tizen { namespace Ui { namespace Effects
69 EffectsSet _EffectImpl::__effects = EffectsSet();
70 RenderControlsMap _EffectImpl::__renderControls = RenderControlsMap();
71 EffectsControlsMap _EffectImpl::__effectsControlsMapRegistered = EffectsControlsMap();
72 ControlsSet _EffectImpl::__controlsSetPerforming = ControlsSet();
73 long _EffectImpl::__effectsCount = 0;
75 _EffectImpl::_EffectImpl(Effect& effect)
79 , __pEventListener(null)
80 , __pResourceProvider(null)
82 , __renderTargetSet(false)
85 __pEffect->__pEffectImpl = this;
88 _EffectImpl::~_EffectImpl(void)
90 Stop(); // <-- checking for result is not necessary (Effect must be stopped before deleting)
92 __effects.erase(__pEffect);
95 //surface deleting if it is not used in other effects
96 EffectsControlsMap::const_iterator itEffectControl;
97 itEffectControl = __effectsControlsMapRegistered.find(__pEffect);
99 //if render target is set then release render target (delete GLSurface and pointers)
100 if (itEffectControl != __effectsControlsMapRegistered.end())
102 ReleaseRenderTarget(*(itEffectControl->second));
107 _EffectImpl::ReleaseRenderTarget(const Control& control)
109 RenderControlsMap::const_iterator itRenderControl = __renderControls.find(&control);
110 SysAssertf(itRenderControl != __renderControls.end(), _UiEffectError::INTERNAL_ERROR);
111 __effectsControlsMapRegistered.erase(__pEffect);
112 bool isDelete = true;
113 if (!__effectsControlsMapRegistered.empty())
115 for (EffectsControlsMap::const_iterator itEffectControl = __effectsControlsMapRegistered.begin();
116 itEffectControl != __effectsControlsMapRegistered.end();
119 if (itEffectControl->second == itRenderControl->first)
128 __pRenderer->ReleaseCache();
129 __pRenderer->surface = EGL_NO_SURFACE;
130 EffectRenderer::DeleteSurface(itRenderControl->second);
131 __renderControls.erase(itRenderControl->first);
136 _EffectImpl::SetRenderTarget(const Tizen::Ui::Control* pControl)
138 SysTryLogReturn(NID_UI_EFFECT, __pRenderer != null, E_OPERATION_FAILED, "Rendering is unavailable for this effect");
140 //checking for effect running
141 SysTryReturn(NID_UI_EFFECT, !IsRunning(), E_IN_PROGRESS, E_IN_PROGRESS,
142 "Effects. [E_IN_PROGRESS] Effect is running now");
144 //if render target was set earlier
145 EffectsControlsMap::const_iterator itEffectsControlsMap = __effectsControlsMapRegistered.find(__pEffect);
146 if (itEffectsControlsMap != __effectsControlsMapRegistered.end())
148 const Control* pControlOld = itEffectsControlsMap->second;
149 if (pControl == null)
151 ReleaseRenderTarget(*pControlOld);
154 //if new and old controls are the same
155 if (pControlOld == pControl)
159 return SetRenderTargetInternal(*pControl, *pControlOld);
161 else//if render target wasn't set earlier
163 if (pControl == null)
169 return SetRenderTargetInternal(*pControl, *pControl);
175 _EffectImpl::SetRenderTargetInternal(const Control& control, const Control& controlOld)
177 __pRenderer->surface = FindGlesSurface(&control);
179 if (__pRenderer->surface == EGL_NO_SURFACE)
181 __pRenderer->surface = EffectRenderer::CreateSurface((EGLNativeWindowType)&control);
182 SysTryReturn(NID_UI_EFFECT, __pRenderer->surface != EGL_NO_SURFACE, E_OPERATION_FAILED, E_OPERATION_FAILED, "Creation of OpenGL surface for effect \"%s\" failed", __pModel->GetName().c_str());
183 SysLog(NID_UI_EFFECT, "Effects. EGL surface is created successfully");
184 if (&controlOld != &control)
186 ReleaseRenderTarget(controlOld);
188 __renderControls.insert(RenderControlsMapPair(&control, __pRenderer->surface));
191 __pRenderer->SetScreen(control);
193 //Reserve memory for texture for less latency on bitmap upload
194 Dimension realControlSize = _CoordinateSystemUtils::Transform(control.GetSize());
195 const RenderDataSurfaceCollection& renderData = __pModel->GetRenderingData()->GetRenderDataSurfaceCollection();
196 RenderDataSurfaceCollection::const_iterator it = renderData.begin();
197 RenderDataSurfaceCollection::const_iterator itend = renderData.end();
198 for (; it != itend; ++it)
200 __pRenderer->SetBitmap((*it)->bitmapId, null, realControlSize.width, realControlSize.height);
203 __pRenderer->BuildCache();
205 __effectsControlsMapRegistered.insert(std::make_pair(__pEffect, &control));
211 _EffectImpl::Start(const Tizen::Base::Collection::IList& effectStartInfo)
213 START_PROFILER(PROFLOG_StartEffect)
215 int countCollection = effectStartInfo.GetCount();
216 EffectsVector<float> effectStartInfoVector(countCollection);
217 for (int i = 0; i < countCollection; ++i)
219 effectStartInfoVector[i] = static_cast<const Float*>(effectStartInfo.GetAt(i))->ToFloat();
222 SysAssertf(__pModel != null, _UiEffectError::INTERNAL_ERROR);
224 if (__pEventListener == null)
226 SysLog(NID_UI_EFFECT, _UiEffectError::LISTENER_IS_NOT_ASSIGNED, __pModel->GetName().c_str());
228 if (__pResourceProvider == null)
230 SysLog(NID_UI_EFFECT, _UiEffectError::PROVIDER_IS_NOT_ASSIGNED, __pModel->GetName().c_str());
233 _EffectState effState = __pModel->GetState();
234 SysTryReturn(NID_UI_EFFECT, effState != _EFFECT_STATE_RUNTIME_ERROR, E_OPERATION_FAILED, E_OPERATION_FAILED, "Attempt to Start an Effect with RUNTIME_ERROR state, effect \"%s\"", __pModel->GetName().c_str());
235 SysTryReturn(NID_UI_EFFECT, effState != _EFFECT_STATE_RUNNING, E_INVALID_STATE, E_INVALID_STATE, "Attempt to Start an Effect that is currently running, effect \"%s\"", __pModel->GetName().c_str());
236 SysTryReturn(NID_UI_EFFECT, effState == _EFFECT_STATE_RUNNABLE, E_OPERATION_FAILED, E_OPERATION_FAILED, "Attempt to Start an Effect that is not runnable, effect \"%s\"", __pModel->GetName().c_str());
238 EffectsControlsMap::iterator iterRegistered = __effectsControlsMapRegistered.find(__pEffect);
240 __renderTargetSet = __pRenderer != null && iterRegistered != __effectsControlsMapRegistered.end();
241 if (!__renderTargetSet)
243 SysLog(NID_UI_EFFECT, "Effect has no attached surface for rendering, effect \"%s\" ", __pModel->GetName().c_str());
247 for (ControlsSet::iterator iterPerforming = __controlsSetPerforming.begin(); iterPerforming != __controlsSetPerforming.end(); ++iterPerforming)
249 SysTryReturn(NID_UI_EFFECT, iterRegistered->second != *iterPerforming, E_ALREADY_SET, E_ALREADY_SET, "Attempt to Start more than one Effect on the same Control, effect \"%s\" ", __pModel->GetName().c_str());
251 __controlsSetPerforming.insert(iterRegistered->second);
255 SysTryCatch(NID_UI_EFFECT, SETJMP == 0, , GetLastResult(), "[%s] Propagating", GetErrorMessage(GetLastResult()));
257 startResult = __pModel->Start(effectStartInfoVector);
261 SysLog(NID_UI_EFFECT, "Effect [%i, %s] was started successfully", __pModel->GetId(), __pModel->GetName().c_str());
264 SysLogException(NID_UI_EFFECT, E_OPERATION_FAILED, "The effect [%i, %s] is not runnable", __pModel->GetId(), __pModel->GetName().c_str());
265 return E_OPERATION_FAILED;
267 SysLogException(NID_UI_EFFECT, E_OPERATION_FAILED, _UiEffectError::LUA_INTERNAL_ERROR, __pModel->GetId(), __pModel->GetName().c_str());
268 return E_OPERATION_FAILED;
270 SysLogException(NID_UI_EFFECT, E_OPERATION_FAILED, "Some error was appeared in function SetBitmap of resources provider for effect [%i, %s]", __pModel->GetId(), __pModel->GetName().c_str());
271 return E_OPERATION_FAILED;
273 SysLogException(NID_UI_EFFECT, E_OPERATION_FAILED, "Unknown error in effect [%i, %s]", __pModel->GetId(), __pModel->GetName().c_str());
274 return E_OPERATION_FAILED;
277 __modelTimer.Reset();
278 __modelTimer.Start(1);
280 END_PROFILER(PROFLOG_StartEffect)
286 __pModel->Stop(true, false);
287 return E_OPERATION_FAILED;
292 _EffectImpl::Stop(void)
294 if (__pModel == null)
299 if (__pModel->GetState() == _EFFECT_STATE_RUNNING)
301 __pModel->Stop(false, true);
302 EffectModelTimerStop();
308 return E_INVALID_STATE;
313 _EffectImpl::FeedTouchPressEvent(const Tizen::Ui::TouchEventInfo& touchEventInfo, const Tizen::Graphics::Point& offset)
315 SysAssertf(__pModel != null, _UiEffectError::INTERNAL_ERROR);
317 SysTryLogReturn(NID_UI_EFFECT, __pRenderer != null, E_OPERATION_FAILED, "Rendering is unavailable for this effect");
319 TouchEventScript touchEventScript = {__pRenderer->TransformScreenToWorld(Vec2f(touchEventInfo.GetCurrentPosition().x, touchEventInfo.GetCurrentPosition().y)),
320 __pRenderer->TransformScreenToWorld(Vec2f(touchEventInfo.GetStartPosition().x, touchEventInfo.GetStartPosition().y)),
321 touchEventInfo.GetPointId()};
323 __pModel->FeedTouchPressEvent(touchEventScript);
324 return GetLastResult();
328 _EffectImpl::FeedTouchMoveEvent(const Tizen::Ui::TouchEventInfo& touchEventInfo, const Tizen::Graphics::Point& offset)
330 SysAssertf(__pModel != null, _UiEffectError::INTERNAL_ERROR);
332 SysTryLogReturn(NID_UI_EFFECT, __pRenderer != null, E_OPERATION_FAILED, "Rendering is unavailable for this effect");
334 TouchEventScript touchEventScript = {__pRenderer->TransformScreenToWorld(Vec2f(touchEventInfo.GetCurrentPosition().x, touchEventInfo.GetCurrentPosition().y)),
335 __pRenderer->TransformScreenToWorld(Vec2f(touchEventInfo.GetStartPosition().x, touchEventInfo.GetStartPosition().y)),
336 touchEventInfo.GetPointId()};
338 __pModel->FeedTouchMoveEvent(touchEventScript);
339 return GetLastResult();
343 _EffectImpl::FeedTouchReleaseEvent(const Tizen::Ui::TouchEventInfo& touchEventInfo, const Tizen::Graphics::Point& offset)
345 SysAssertf(__pModel != null, _UiEffectError::INTERNAL_ERROR);
347 SysTryLogReturn(NID_UI_EFFECT, __pRenderer != null, E_OPERATION_FAILED, "Rendering is unavailable for this effect");
349 TouchEventScript touchEventScript = {__pRenderer->TransformScreenToWorld(Vec2f(touchEventInfo.GetCurrentPosition().x, touchEventInfo.GetCurrentPosition().y)),
350 __pRenderer->TransformScreenToWorld(Vec2f(touchEventInfo.GetStartPosition().x, touchEventInfo.GetStartPosition().y)),
351 touchEventInfo.GetPointId()};
353 __pModel->FeedTouchReleaseEvent(touchEventScript);
354 return GetLastResult();
358 _EffectImpl::FeedTouchDoublePressEvent(const Tizen::Ui::TouchEventInfo& touchEventInfo, const Tizen::Graphics::Point& offset)
360 SysAssertf(__pModel != null, _UiEffectError::INTERNAL_ERROR);
362 SysTryLogReturn(NID_UI_EFFECT, __pRenderer != null, E_OPERATION_FAILED, "Rendering is unavailable for this effect");
364 TouchEventScript touchEventScript = {__pRenderer->TransformScreenToWorld(Vec2f(touchEventInfo.GetCurrentPosition().x, touchEventInfo.GetCurrentPosition().y)),
365 __pRenderer->TransformScreenToWorld(Vec2f(touchEventInfo.GetStartPosition().x, touchEventInfo.GetStartPosition().y)),
366 touchEventInfo.GetPointId()};
368 __pModel->FeedTouchDoublePressEvent(touchEventScript);
369 return GetLastResult();
373 _EffectImpl::SetBitmap(long bitmapId, const Bitmap& bitmap)
375 SysTryLogReturn(NID_UI_EFFECT, __pRenderer != null, E_OPERATION_FAILED, "Rendering is unavailable for this effect");
379 // Analysing non existing bitmap ID in Effect Project [with E_OBJ_NOT_FOUND]
380 const RenderDataSurfaceCollection& renderData = __pModel->GetRenderingData()->GetRenderDataSurfaceCollection();
381 RenderDataSurfaceCollection::const_iterator it = renderData.begin();
382 RenderDataSurfaceCollection::const_iterator itend = renderData.end();
383 for (; it != itend; ++it)
385 if ((*it)->bitmapId == bitmapId)
391 SysTryReturn(NID_UI_EFFECT, resOk, E_OPERATION_FAILED, E_OPERATION_FAILED, "Bitmap with specified id does not exist");
393 resOk = __pRenderer->SetBitmap(bitmapId, const_cast<Tizen::Graphics::Bitmap &>(bitmap));
394 return (resOk ? E_SUCCESS : E_OPERATION_FAILED);
398 _EffectImpl::IsRunning(void) const
400 SysAssertf(__pModel != null, _UiEffectError::INTERNAL_ERROR);
402 _EffectState effectState = __pModel->GetState();
403 return (effectState == _EFFECT_STATE_RUNNING);
407 _EffectImpl::GetType(void) const
409 SysAssertf(__pModel != null, _UiEffectError::INTERNAL_ERROR);
410 return __pModel->GetType();
414 _EffectImpl::GetName(void) const
416 return String(__pModel->GetName().c_str());
420 _EffectImpl::SetEffectEventListener(IEffectEventListener* pListener)
422 __pEventListener = pListener;
426 IEffectEventListener*
427 _EffectImpl::GetEffectEventListener(void) const
429 return __pEventListener;
433 _EffectImpl::SetResourceProvider(IEffectResourceProvider* pProvider)
435 __pResourceProvider = pProvider;
439 IEffectResourceProvider*
440 _EffectImpl::GetResourceProvider(void) const
442 return __pResourceProvider;
446 _EffectImpl::FindGlesSurface(const Control* pControl) const
448 RenderControlsMap::const_iterator it = __renderControls.find(pControl);
450 if (it != __renderControls.end())
455 return EGL_NO_SURFACE;
459 _EffectImpl::EffectModelTimerStop(void)
467 _EffectImpl::OnTimerExpired(Timer& timer)
469 _EffectTimer* pEffectTimer = dynamic_cast<_EffectTimer*>(&timer);
470 SysAssertf(pEffectTimer != null, _UiEffectError::INTERNAL_ERROR);
471 SysAssertf(__pModel != null, _UiEffectError::INTERNAL_ERROR);
473 if (__pModel->GetState() == _EFFECT_STATE_RUNNING)
475 __modelTimer.Start();
476 __pModel->Calculate(pEffectTimer->CalculationTimeStep()); // actual time period between calls OnTimerExpied function
478 if (__pModel->GetState() != _EFFECT_STATE_RUNNING)
483 if ((__renderTargetSet) && (__pModel->GetState() == _EFFECT_STATE_RUNNING))
485 __pModel->UpdateGraphicalSurfaces();
488 __pRenderer->Update();
495 __pModel->Stop(true, false);
497 SysLogException(NID_UI_EFFECT, GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
510 _EffectImpl::UpdateScreen(void)
512 EffectsControlsMap::const_iterator itEffCtrl = __effectsControlsMapRegistered.find(__pEffect);
513 SysAssertf(itEffCtrl != __effectsControlsMapRegistered.end(), _UiEffectError::INTERNAL_ERROR);
515 __pRenderer->TrackScreenSizeChanges(*itEffCtrl->second);
521 _EffectImpl::OnEffectStarted(void)
523 if (__renderTargetSet)
525 __pModel->UpdateGraphicalSurfaces();
526 __pRenderer->Update();
532 if (__pEventListener != null)
534 __pEventListener->OnEffectStarted(*__pEffect);
545 _EffectImpl::OnEffectFinished(EffectResult effectResult, const LastShownBitmapIdCollection& bitmapsTargetId)
547 SysAssertf(__pModel != null, _UiEffectError::INTERNAL_ERROR);
549 if (__renderTargetSet && __pModel->GetState() != _EFFECT_STATE_RUNTIME_ERROR)
551 __pModel->UpdateGraphicalSurfaces();
552 __pRenderer->Update();
558 EffectsControlsMap::iterator it = __effectsControlsMapRegistered.find(__pEffect);
559 if (it != __effectsControlsMapRegistered.end())
561 __controlsSetPerforming.erase(it->second);
564 if (__pEventListener != null)
566 ArrayList lastShownBitmapId;
567 result res = lastShownBitmapId.Construct();
568 SysAssertf(res != E_INVALID_ARG, _UiEffectError::INTERNAL_ERROR);
570 if (res == E_SUCCESS)
572 for (LastShownBitmapIdCollection::const_iterator it = bitmapsTargetId.begin(); it != bitmapsTargetId.end(); ++it)
574 Long* pLong = new (std::nothrow) Long(*it);
577 lastShownBitmapId.Add(*pLong);
581 SetLastResult(E_OUT_OF_MEMORY);
587 __pEventListener->OnEffectFinished(*__pEffect, effectResult, lastShownBitmapId);
589 lastShownBitmapId.RemoveAll(true);
600 _EffectImpl::OnBitmapRequested(long bitmapId)
602 if (__pResourceProvider != null)
604 return __pResourceProvider->SetBitmap(*__pEffect, bitmapId) == E_SUCCESS;
613 _EffectImpl::InitializeEffect(void)
615 Tizen::App::App* pApp = Tizen::App::App::GetInstance();
616 SysTryReturnVoidResult(NID_UI_EFFECT, pApp != null, E_FILE_NOT_FOUND, "Effects. The pointer to application instance equals null");
617 std::wstring tempWStr = std::wstring((pApp->GetAppRootPath()).GetPointer());
618 tempWStr += L"data/";
619 std::string dataDirStr(tempWStr.begin(), tempWStr.end());
621 SysAssertf(_EffectManagerImpl::__pPathToEffectFile != null, _UiEffectError::INTERNAL_ERROR);
623 int modelTimerTimeout;
624 IEffectModelManager* pModelTemp;
625 EffectRenderer* pRendererTemp;
626 result res = EffectParser::ParseEffectFileLoadModel(_EffectManagerImpl::__pPathToEffectFile, dataDirStr.c_str(), this, __effectsCount, pModelTemp, pRendererTemp, modelTimerTimeout);
627 _EffectManagerImpl::__pPathToEffectFile = null;
629 //E_OUT_OF_MEMORY or E_PARSING_FAILED:
630 if ((res != E_SUCCESS) && (res != E_OUT_OF_MEMORY))
632 res = E_PARSING_FAILED;
634 SysTryReturnVoidResult(NID_UI_EFFECT, res == E_SUCCESS, res, "[%s] Propagating", GetErrorMessage(res));
636 __pModel.reset(pModelTemp);
637 __pRenderer.reset(pRendererTemp);
639 SysAssertf(__pModel != null, _UiEffectError::INTERNAL_ERROR);
640 SysAssertf(modelTimerTimeout > 0, _UiEffectError::INTERNAL_ERROR);
642 res = __modelTimer.Construct(*this, __pModel->GetId(), modelTimerTimeout);
643 res = (res == E_SYSTEM ? E_PARSING_FAILED : res);
644 SysTryReturnVoidResult(NID_UI_EFFECT, res == E_SUCCESS, res, "[%s] Propagating", GetErrorMessage(res));
646 std::pair<EffectsSet::iterator, bool> resultInsert = __effects.insert(__pEffect);
647 SysAssertf(resultInsert.second == true, _UiEffectError::INTERNAL_ERROR);
649 bool isLuaError = (__pModel->GetState() != _EFFECT_STATE_RUNNABLE);
650 SysTryReturnVoidResult(NID_UI_EFFECT, !isLuaError, E_PARSING_FAILED, _UiEffectError::LUA_RUNTIME_ERROR);
653 }}} // Tizen::Ui::Effects