(FrameCallback) Ensure Update doesn't invoke removed FrameCallbacks
[platform/core/uifw/dali-core.git] / dali / internal / event / common / stage-impl.cpp
index 9e10b2e..b205860 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/internal/event/common/thread-local-storage.h>
 #include <dali/internal/event/common/property-notification-manager.h>
 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
+#include <dali/internal/event/update/frame-callback-interface-impl.h>
 #include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/manager/scene-graph-frame-callback.h>
 #include <dali/internal/event/common/object-registry-impl.h>
 #include <dali/integration-api/platform-abstraction.h>
 #include <dali/public-api/common/constants.h>
 #include <dali/public-api/events/touch-data.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/public-api/rendering/frame-buffer.h>
 
 using Dali::Internal::SceneGraph::Node;
 
@@ -95,8 +98,9 @@ StagePtr Stage::New( AnimationPlaylist& playlist,
   return StagePtr( new Stage( playlist, propertyNotificationManager, updateManager, notificationManager, renderController ) );
 }
 
-void Stage::Initialize()
+void Stage::Initialize( bool renderToFbo )
 {
+  mRenderToFbo = renderToFbo;
   mObjectRegistry = ObjectRegistry::New();
 
   // Create the ordered list of layers
@@ -200,14 +204,14 @@ void Stage::Remove( Actor& actor )
 
 void Stage::SurfaceResized( float width, float height )
 {
-  if( ( fabs( width - mSurfaceSize.width ) > Math::MACHINE_EPSILON_1000 ) || ( fabs( height - mSurfaceSize.height ) > Math::MACHINE_EPSILON_1000 ) )
+  if( ( fabsf( width - mSurfaceSize.width ) > Math::MACHINE_EPSILON_1000 ) || ( fabsf( height - mSurfaceSize.height ) > Math::MACHINE_EPSILON_1000 ) )
   {
     mSurfaceSize.width = width;
     mSurfaceSize.height = height;
 
     // Internally we want to report the actual size of the stage.
     mSize.width = width;
-    mSize.height = height - mTopMargin;
+    mSize.height = height - static_cast<float>( mTopMargin );
 
     // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position.
     mDefaultCamera->SetPerspectiveProjection( mSurfaceSize );
@@ -225,18 +229,28 @@ void Stage::SurfaceResized( float width, float height )
       mSystemOverlay->GetImpl()->SetSize( width, height );
     }
 
-    SetDefaultSurfaceRectMessage( mUpdateManager, Rect<int>( 0, 0, width, height ) );
+    SetDefaultSurfaceRectMessage( mUpdateManager, Rect<int32_t>( 0, 0, static_cast<int32_t>( width ), static_cast<int32_t>( height ) ) ); // truncated
 
     // if single render task to screen then set its viewport parameters
     if( 1 == mRenderTaskList->GetTaskCount() )
     {
-      Dali::RenderTask mDefaultRenderTask = mRenderTaskList->GetTask( 0u );
+      Dali::RenderTask defaultRenderTask = mRenderTaskList->GetTask( 0u );
 
-      if(!mDefaultRenderTask.GetTargetFrameBuffer())
+      if(!defaultRenderTask.GetTargetFrameBuffer())
       {
-        mDefaultRenderTask.SetViewport( Viewport(0, 0, width, height) );
+        defaultRenderTask.SetViewport( Viewport( 0, 0, static_cast<int32_t>( width ), static_cast<int32_t>( height ) ) ); // truncated
       }
     }
+
+    if( mRenderToFbo )
+    {
+      Dali::FrameBuffer frameBuffer = Dali::FrameBuffer::New( static_cast<uint32_t>( width ), static_cast<uint32_t>( height ), Dali::FrameBuffer::Attachment::NONE );
+      Dali::Texture texture = Dali::Texture::New( Dali::TextureType::TEXTURE_2D, Dali::Pixel::RGB888, static_cast<uint32_t>( width ), static_cast<uint32_t>( height ) );
+      frameBuffer.AttachColorTexture( texture );
+
+      Dali::RenderTask defaultRenderTask = mRenderTaskList->GetTask( 0u );
+      defaultRenderTask.SetFrameBuffer( frameBuffer );
+    }
   }
 }
 
@@ -245,7 +259,7 @@ Vector2 Stage::GetSize() const
   return mSize;
 }
 
-void Stage::SetTopMargin( unsigned int margin )
+void Stage::SetTopMargin( uint32_t margin )
 {
   if (mTopMargin == margin)
   {
@@ -254,7 +268,7 @@ void Stage::SetTopMargin( unsigned int margin )
   mTopMargin = margin;
 
   mSize.width = mSurfaceSize.width;
-  mSize.height = mSurfaceSize.height - mTopMargin;
+  mSize.height = mSurfaceSize.height - static_cast<float>( mTopMargin );
 
   // Adjust the camera height to allow for top-margin
   SetDefaultCameraPosition();
@@ -292,12 +306,12 @@ CameraActor& Stage::GetDefaultCameraActor()
   return *mDefaultCamera;
 }
 
-unsigned int Stage::GetLayerCount() const
+uint32_t Stage::GetLayerCount() const
 {
   return mLayerList->GetLayerCount();
 }
 
-Dali::Layer Stage::GetLayer( unsigned int depth ) const
+Dali::Layer Stage::GetLayer( uint32_t depth ) const
 {
   return Dali::Layer(mLayerList->GetLayer( depth ));
 }
@@ -406,13 +420,13 @@ void Stage::SetViewMode( ViewMode viewMode )
 
         mLeftCamera->SetOrientation( -Dali::ANGLE_90, Vector3::ZAXIS );
         mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
-        mLeftRenderTask.SetViewport( Viewport(0, mSize.height * 0.5f, mSize.width, mSize.height * 0.5f) );
+        mLeftRenderTask.SetViewport( Viewport(0, static_cast<int32_t>( mSize.height * 0.5f ), static_cast<int32_t>( mSize.width ), static_cast<int32_t>( mSize.height * 0.5f ) ) ); // truncated
 
-        mRightCamera->SetPerspectiveProjection( mSize, Vector2( 0.0,  -stereoBase) );
+        mRightCamera->SetPerspectiveProjection( mSize, Vector2( 0.0,  -stereoBase ) );
         mRightCamera->SetAspectRatio( aspect );
         mRightCamera->SetOrientation( -Dali::ANGLE_90, Vector3::ZAXIS );
         mRightCamera->SetPosition( Vector3(-stereoBase, 0.0f, 0.0f ) );
-        mRightRenderTask.SetViewport( Viewport(0, 0, mSize.width, mSize.height * 0.5f ) );
+        mRightRenderTask.SetViewport( Viewport(0, 0, static_cast<int32_t>( mSize.width ), static_cast<int32_t>( mSize.height * 0.5f ) ) ); // truncated
 
         break;
       }
@@ -428,13 +442,13 @@ void Stage::SetViewMode( ViewMode viewMode )
         mLeftCamera->SetFieldOfView( fov );
         mLeftCamera->SetOrientation( Dali::ANGLE_0, Vector3::ZAXIS );
         mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
-        mLeftRenderTask.SetViewport( Viewport(0, 0, mSize.width * 0.5f, mSize.height ) );
+        mLeftRenderTask.SetViewport( Viewport(0, 0, static_cast<int32_t>( mSize.width * 0.5f ), static_cast<int32_t>( mSize.height ) ) ); // truncated
 
         mRightCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(-stereoBase,0.0f) );
         mRightCamera->SetFieldOfView( fov );
         mRightCamera->SetOrientation( Dali::ANGLE_0, Vector3::ZAXIS );
         mRightCamera->SetPosition( Vector3( -stereoBase, 0.0f, 0.0f ) );
-        mRightRenderTask.SetViewport( Viewport(mSize.width * 0.5f, 0, mSize.width * 0.5f, mSize.height ) );
+        mRightRenderTask.SetViewport( Viewport( static_cast<int32_t>( mSize.width * 0.5f ), 0, static_cast<int32_t>( mSize.width * 0.5f ), static_cast<int32_t>( mSize.height ) ) ); // truncated
 
         break;
       }
@@ -531,6 +545,22 @@ void Stage::KeepRendering( float durationSeconds )
   KeepRenderingMessage( mUpdateManager, durationSeconds );
 }
 
+void Stage::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
+{
+  if( mRenderingBehavior != renderingBehavior )
+  {
+    // Send message to change the rendering behavior
+    SetRenderingBehaviorMessage( mUpdateManager, renderingBehavior );
+
+    mRenderingBehavior = renderingBehavior;
+  }
+}
+
+DevelStage::Rendering Stage::GetRenderingBehavior() const
+{
+  return mRenderingBehavior;
+}
+
 bool Stage::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
 {
   bool connected( true );
@@ -628,6 +658,22 @@ Dali::DevelStage::KeyEventGeneratedSignalType& Stage::KeyEventGeneratedSignal()
   return mKeyEventGeneratedSignal;
 }
 
+void Stage::AddFrameCallback( FrameCallbackInterface& frameCallback, Actor& rootActor )
+{
+  DALI_ASSERT_ALWAYS( ( ! FrameCallbackInterface::Impl::Get( frameCallback ).IsConnectedToSceneGraph() )
+                      && "FrameCallbackInterface implementation already added" );
+
+  // Create scene-graph object and transfer to UpdateManager
+  OwnerPointer< SceneGraph::FrameCallback > transferOwnership( SceneGraph::FrameCallback::New( frameCallback ) );
+  AddFrameCallbackMessage( mUpdateManager, transferOwnership, rootActor.GetNode() );
+}
+
+void Stage::RemoveFrameCallback( FrameCallbackInterface& frameCallback )
+{
+  FrameCallbackInterface::Impl::Get( frameCallback ).Invalidate();
+  RemoveFrameCallbackMessage( mUpdateManager, frameCallback );
+}
+
 Dali::Stage::EventProcessingFinishedSignalType& Stage::EventProcessingFinishedSignal()
 {
   return mEventProcessingFinishedSignal;
@@ -706,13 +752,28 @@ Stage::Stage( AnimationPlaylist& playlist,
   mNotificationManager( notificationManager ),
   mRenderController( renderController ),
   mSize( Vector2::ZERO ),
+  mSurfaceSize( Vector2::ZERO ),
   mBackgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
   mViewMode( MONO ),
   mStereoBase( DEFAULT_STEREO_BASE ),
   mTopMargin( 0 ),
+  mDpi( Vector2::ZERO ),
+  mRightRenderTask(),
+  mLeftRenderTask(),
   mSystemOverlay( NULL ),
+  mKeyEventSignal(),
+  mKeyEventGeneratedSignal(),
+  mEventProcessingFinishedSignal(),
+  mTouchedSignal(),
+  mTouchSignal(),
+  mWheelEventSignal(),
+  mContextLostSignal(),
+  mContextRegainedSignal(),
+  mSceneCreatedSignal(),
+  mRenderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
   mDepthTreeDirty( false ),
-  mForceNextUpdate( false )
+  mForceNextUpdate( false ),
+  mRenderToFbo( false )
 {
 }
 
@@ -726,7 +787,7 @@ Integration::RenderController& Stage::GetRenderController()
   return mRenderController;
 }
 
-unsigned int* Stage::ReserveMessageSlot( std::size_t size, bool updateScene )
+uint32_t* Stage::ReserveMessageSlot( uint32_t size, bool updateScene )
 {
   return mUpdateManager.ReserveMessageSlot( size, updateScene );
 }