Dali 3D User Interface Engine
adaptor-impl.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 // CLASS HEADER
19 #include "adaptor-impl.h"
20 
21 // EXTERNAL INCLUDES
29 
30 // INTERNAL INCLUDES
31 #include <base/thread-controller.h>
34 
35 #include <dali/devel-api/text-abstraction/font-client.h>
36 
37 #include <callback-manager.h>
38 #include <render-surface.h>
39 #include <tts-player-impl.h>
41 #include <events/gesture-manager.h>
42 #include <events/event-handler.h>
44 #include <gl/gl-implementation.h>
47 #include <gl/egl-factory.h>
48 #include <imf-manager-impl.h>
49 #include <clipboard-impl.h>
50 #include <vsync-monitor.h>
51 #include <object-profiler.h>
53 #include <window-impl.h>
54 
55 #include <tizen-logging.h>
56 
57 using Dali::TextAbstraction::FontClient;
58 
59 namespace Dali
60 {
61 
62 namespace Internal
63 {
64 
65 namespace Adaptor
66 {
67 
68 namespace
69 {
70 __thread Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
71 } // unnamed namespace
72 
73 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
74 {
75  Dali::Adaptor* adaptor = new Dali::Adaptor;
76  Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface, environmentOptions );
77  adaptor->mImpl = impl;
78 
79  impl->Initialize(configuration);
80 
81  return adaptor;
82 }
83 
84 Dali::Adaptor* Adaptor::New( Dali::Window window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
85 {
86  Any winId = window.GetNativeHandle();
87 
88  Window& windowImpl = Dali::GetImplementation(window);
89  Dali::Adaptor* adaptor = New( winId, windowImpl.GetSurface(), configuration, environmentOptions );
90  windowImpl.SetAdaptor(*adaptor);
91  return adaptor;
92 }
93 
94 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
95 {
96  // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
98  mEnvironmentOptions->SetLogFunction( logFunction );
99  mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
100 
102 
103  std::string path;
104  GetDataStoragePath( path );
106 
109  {
110  dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
111  }
112  // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
113  // files automatically.
114 
116  {
118  }
119 
121 
122  PositionSize size = mSurface->GetPositionSize();
123 
125 
127  {
129  }
130  else
131  {
132  mGLES = new GlImplementation();
133  }
134 
135  mEglFactory = new EglFactory();
136 
138 
139  mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
140 
141  const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
142  if( 0u < timeInterval )
143  {
144  mObjectProfiler = new ObjectProfiler( timeInterval );
145  }
146 
147  mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
148 
150 
152 
153  // Should be called after Core creation
155  {
157  }
159  {
161  }
163  {
165  }
167  {
169  }
171  {
173  }
175  {
177  }
179  {
181  }
183  {
185  }
186 }
187 
188 Adaptor::~Adaptor()
189 {
190  // Ensure stop status
191  Stop();
192 
193  // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
194  gThreadLocalAdaptor = NULL;
195 
196  for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
197  {
198  (*iter)->OnDestroy();
199  }
200 
201  delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
202  delete mVSyncMonitor;
203  delete mEventHandler;
204  delete mObjectProfiler;
205 
206  delete mCore;
207  delete mEglFactory;
208  delete mGLES;
209  delete mGestureManager;
210  delete mPlatformAbstraction;
211  delete mCallbackManager;
212  delete mPerformanceInterface;
213 
214  // uninstall it on this thread (main actor thread)
216 
217  // Delete environment options if we own it
219  {
220  delete mEnvironmentOptions;
221  }
222 }
223 
224 void Adaptor::Start()
225 {
226  // it doesn't support restart after stop at this moment
227  // to support restarting, need more testing
228  if( READY != mState )
229  {
230  return;
231  }
232 
233  // Start the callback manager
235 
236  // create event handler
238 
239  if( mDeferredRotationObserver != NULL )
240  {
243  }
244 
245  unsigned int dpiHor, dpiVer;
246  dpiHor = dpiVer = 0;
247  Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
248 
249  // tell core about the DPI value
250  mCore->SetDpi(dpiHor, dpiVer);
251 
252  // set the DPI value for font rendering
253  FontClient fontClient = FontClient::Get();
254  fontClient.SetDpi( dpiHor, dpiVer );
255 
256  // Tell the core the size of the surface just before we start the render-thread
257  PositionSize size = mSurface->GetPositionSize();
258  mCore->SurfaceResized( size.width, size.height );
259 
260  // Initialize the thread controller
262 
263  mState = RUNNING;
264 
265  ProcessCoreEvents(); // Ensure any startup messages are processed.
266 
267  for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
268  {
269  (*iter)->OnStart();
270  }
271 }
272 
273 // Dali::Internal::Adaptor::Adaptor::Pause
274 void Adaptor::Pause()
275 {
276  // Only pause the adaptor if we're actually running.
277  if( RUNNING == mState )
278  {
279  // Inform observers that we are about to be paused.
280  for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
281  {
282  (*iter)->OnPause();
283  }
284 
285  // Reset the event handler when adaptor paused
286  if( mEventHandler )
287  {
288  mEventHandler->Pause();
289  }
290 
292  mCore->Suspend();
293  mState = PAUSED;
294  }
295 }
296 
297 // Dali::Internal::Adaptor::Adaptor::Resume
298 void Adaptor::Resume()
299 {
300  // Only resume the adaptor if we are in the suspended state.
301  if( PAUSED == mState )
302  {
303  mState = RUNNING;
304 
305  // Reset the event handler when adaptor resumed
306  if( mEventHandler )
307  {
309  }
310 
311  // Inform observers that we have resumed.
312  for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
313  {
314  (*iter)->OnResume();
315  }
316 
317  // Resume core so it processes any requests as well
318  mCore->Resume();
319 
320  // Do at end to ensure our first update/render after resumption includes the processed messages as well
322  }
323 }
324 
325 void Adaptor::Stop()
326 {
327  if( RUNNING == mState ||
328  PAUSED == mState ||
330  {
331  for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
332  {
333  (*iter)->OnStop();
334  }
335 
337  mCore->Suspend();
338 
339  // Delete the TTS player
340  for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
341  {
342  if(mTtsPlayers[i])
343  {
344  mTtsPlayers[i].Reset();
345  }
346  }
347 
348  delete mEventHandler;
349  mEventHandler = NULL;
350 
351  delete mNotificationTrigger;
352  mNotificationTrigger = NULL;
353 
355 
356  mState = STOPPED;
357  }
358 }
359 
360 void Adaptor::ContextLost()
361 {
362  mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
363 }
364 
365 void Adaptor::ContextRegained()
366 {
367  // Inform core, so that texture resources can be reloaded
369 
370  mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
371 }
372 
373 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
374 {
375  mEventHandler->FeedTouchPoint( point, timeStamp );
376 }
377 
378 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
379 {
380  mEventHandler->FeedWheelEvent( wheelEvent );
381 }
382 
383 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
384 {
385  mEventHandler->FeedKeyEvent( keyEvent );
386 }
387 
388 bool Adaptor::MoveResize( const PositionSize& positionSize )
389 {
390  PositionSize old = mSurface->GetPositionSize();
391 
392  // just resize the surface. The driver should automatically resize the egl Surface (untested)
393  // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
394  // is resized. Implementations typically use hooks into the OS and native window
395  // system to perform this resizing on demand, transparently to the client.
396  mSurface->MoveResize( positionSize );
397 
398  if(old.width != positionSize.width || old.height != positionSize.height)
399  {
400  SurfaceSizeChanged(positionSize);
401  }
402 
403  return true;
404 }
405 
406 void Adaptor::SurfaceResized( const PositionSize& positionSize )
407 {
408  PositionSize old = mSurface->GetPositionSize();
409 
410  // Called by an application, when it has resized a window outside of Dali.
411  // The EGL driver automatically detects X Window resize calls, and resizes
412  // the EGL surface for us.
413  mSurface->MoveResize( positionSize );
414 
415  if(old.width != positionSize.width || old.height != positionSize.height)
416  {
417  SurfaceSizeChanged(positionSize);
418  }
419 }
420 
421 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
422 {
423  mNativeWindow = nativeWindow;
424  mSurface = &surface;
425 
426  SurfaceSizeChanged(mSurface->GetPositionSize());
427 
428  // flush the event queue to give update and render threads chance
429  // to start processing messages for new camera setup etc as soon as possible
431 
432  // this method blocks until the render thread has completed the replace.
434 }
435 
436 RenderSurface& Adaptor::GetSurface() const
437 {
438  return *mSurface;
439 }
440 
441 void Adaptor::ReleaseSurfaceLock()
442 {
443  mSurface->ReleaseLock();
444 }
445 
446 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
447 {
448  if(!mTtsPlayers[mode])
449  {
450  // Create the TTS player when it needed, because it can reduce launching time.
451  mTtsPlayers[mode] = TtsPlayer::New(mode);
452  }
453 
454  return mTtsPlayers[mode];
455 }
456 
457 bool Adaptor::AddIdle( CallbackBase* callback )
458 {
459  bool idleAdded(false);
460 
461  // Only add an idle if the Adaptor is actually running
462  if( RUNNING == mState )
463  {
464  idleAdded = mCallbackManager->AddIdleCallback( callback );
465  }
466 
467  return idleAdded;
468 }
469 
470 
471 Dali::Adaptor& Adaptor::Get()
472 {
473  DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
475 }
476 
477 bool Adaptor::IsAvailable()
478 {
479  return gThreadLocalAdaptor != NULL;
480 }
481 
482 void Adaptor::SceneCreated()
483 {
484  mCore->SceneCreated();
485 }
486 
487 Dali::Integration::Core& Adaptor::GetCore()
488 {
489  return *mCore;
490 }
491 
492 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
493 {
494  mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
495 }
496 
497 void Adaptor::SetUseHardwareVSync( bool useHardware )
498 {
499  mVSyncMonitor->SetUseHardwareVSync( useHardware );
500 }
501 
502 EglFactory& Adaptor::GetEGLFactory() const
503 {
504  DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
505  return *mEglFactory;
506 }
507 
508 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
509 {
510  return *mEglFactory;
511 }
512 
513 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
514 {
515  DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
516  return *mGLES;
517 }
518 
519 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
520 {
521  return *mPlatformAbstraction;
522 }
523 
524 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
525 {
526  return *mGLES;
527 }
528 
529 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
530 {
531  return *mNotificationTrigger;
532 }
533 
534 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
535 {
536  return mTriggerEventFactory;
537 }
538 
539 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
540 {
541  return mSocketFactory;
542 }
543 
544 RenderSurface* Adaptor::GetRenderSurfaceInterface()
545 {
546  return mSurface;
547 }
548 
549 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
550 {
551  return mVSyncMonitor;
552 }
553 
554 TraceInterface& Adaptor::GetKernelTraceInterface()
555 {
556  return mKernelTracer;
557 }
558 
559 TraceInterface& Adaptor::GetSystemTraceInterface()
560 {
561  return mSystemTracer;
562 }
563 
565 {
566  return mPerformanceInterface;
567 }
568 
569 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
570 {
571  DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
572  return *mPlatformAbstraction;
573 }
574 
575 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
576 {
577  mDragAndDropDetector = detector;
578 
579  if ( mEventHandler )
580  {
582  }
583 }
584 
585 void Adaptor::SetRotationObserver( RotationObserver* observer )
586 {
587  if( mEventHandler )
588  {
589  mEventHandler->SetRotationObserver( observer );
590  }
591  else if( mState == READY )
592  {
593  // Set once event handler exists
594  mDeferredRotationObserver = observer;
595  }
596 }
597 
598 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
599 {
600  if(mTtsPlayers[mode])
601  {
602  mTtsPlayers[mode].Reset();
603  }
604 }
605 
606 void Adaptor::SetMinimumPinchDistance(float distance)
607 {
608  if( mGestureManager )
609  {
611  }
612 }
613 
614 Any Adaptor::GetNativeWindowHandle()
615 {
616  return mNativeWindow;
617 }
618 
619 void Adaptor::AddObserver( LifeCycleObserver& observer )
620 {
621  ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
622 
623  if ( match == mObservers.end() )
624  {
625  mObservers.push_back( &observer );
626  }
627 }
628 
629 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
630 {
631  ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
632 
633  if ( match != mObservers.end() )
634  {
635  mObservers.erase( match );
636  }
637 }
638 
639 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
640 {
641  if( mCore )
642  {
643  mCore->QueueEvent(event);
644  }
645 }
646 
647 void Adaptor::ProcessCoreEvents()
648 {
649  if( mCore )
650  {
652  {
654  }
655 
656  mCore->ProcessEvents();
657 
659  {
661  }
662  }
663 }
664 
665 void Adaptor::RequestUpdate()
666 {
667  // When Dali applications are partially visible behind the lock-screen,
668  // the indicator must be updated (therefore allow updates in the PAUSED state)
669  if ( PAUSED == mState ||
670  RUNNING == mState )
671  {
673  }
674 }
675 
676 void Adaptor::RequestProcessEventsOnIdle()
677 {
678  // Only request a notification if the Adaptor is actually running
679  // and we haven't installed the idle notification
680  if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
681  {
683  }
684 }
685 
686 void Adaptor::OnWindowShown()
687 {
688  if ( PAUSED_WHILE_HIDDEN == mState )
689  {
690  // Adaptor can now be resumed
691  mState = PAUSED;
692 
693  Resume();
694 
695  // Force a render task
697  }
698 }
699 
700 void Adaptor::OnWindowHidden()
701 {
702  if ( STOPPED != mState )
703  {
704  Pause();
705 
706  // Adaptor cannot be resumed until the window is shown
708  }
709 }
710 
711 // Dali::Internal::Adaptor::Adaptor::OnDamaged
712 void Adaptor::OnDamaged( const DamageArea& area )
713 {
714  // This is needed for the case where Dali window is partially obscured
715  RequestUpdate();
716 }
717 
718 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
719 {
720  // let the core know the surface size has changed
721  mCore->SurfaceResized(positionSize.width, positionSize.height);
722 
723  mResizedSignal.Emit( mAdaptor );
724 }
725 
726 void Adaptor::NotifySceneCreated()
727 {
728  GetCore().SceneCreated();
729 
730  // Start thread controller after the scene has been created
732 }
733 
734 void Adaptor::NotifyLanguageChanged()
735 {
737 }
738 
739 void Adaptor::RequestUpdateOnce()
740 {
741  if( PAUSED_WHILE_HIDDEN != mState )
742  {
743  if( mThreadController )
744  {
746  }
747  }
748 }
749 
750 void Adaptor::ProcessCoreEventsFromIdle()
751 {
753 
754  // the idle handle automatically un-installs itself
756 }
757 
758 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
759 : mResizedSignal(),
760  mLanguageChangedSignal(),
761  mAdaptor( adaptor ),
762  mState( READY ),
763  mCore( NULL ),
764  mThreadController( NULL ),
765  mVSyncMonitor( NULL ),
766  mGLES( NULL ),
767  mGlSync( NULL ),
768  mEglFactory( NULL ),
769  mNativeWindow( nativeWindow ),
770  mSurface( surface ),
771  mPlatformAbstraction( NULL ),
772  mEventHandler( NULL ),
773  mCallbackManager( NULL ),
774  mNotificationOnIdleInstalled( false ),
775  mNotificationTrigger( NULL ),
776  mGestureManager( NULL ),
777  mDaliFeedbackPlugin(),
778  mFeedbackController( NULL ),
779  mTtsPlayers(),
780  mObservers(),
781  mDragAndDropDetector(),
782  mDeferredRotationObserver( NULL ),
783  mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
784  mPerformanceInterface( NULL ),
785  mKernelTracer(),
786  mSystemTracer(),
787  mTriggerEventFactory(),
788  mObjectProfiler( NULL ),
789  mSocketFactory(),
790  mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ )
791 {
792  DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
793  gThreadLocalAdaptor = this;
794 }
795 
796 // Stereoscopy
797 
798 void Adaptor::SetViewMode( ViewMode viewMode )
799 {
800  mSurface->SetViewMode( viewMode );
801  mCore->SetViewMode( viewMode );
802 }
803 
804 ViewMode Adaptor::GetViewMode() const
805 {
806  return mCore->GetViewMode();
807 }
808 
809 void Adaptor::SetStereoBase( float stereoBase )
810 {
811  mCore->SetStereoBase( stereoBase );
812 }
813 
814 float Adaptor::GetStereoBase() const
815 {
816  return mCore->GetStereoBase();
817 }
818 
819 } // namespace Adaptor
820 
821 } // namespace Internal
822 
823 } // namespace Dali
Dali Docs Home
Read more about Dali