(Scene) Add frame rendered/presented callback 68/237968/1
authorHeeyong Song <heeyong.song@samsung.com>
Mon, 15 Jun 2020 07:35:01 +0000 (16:35 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Tue, 7 Jul 2020 05:05:48 +0000 (14:05 +0900)
Change-Id: Ic903229e71d76a05a0af24a68b26440d26462fa6

automated-tests/src/dali/utc-Dali-Scene.cpp
dali/integration-api/scene.cpp
dali/integration-api/scene.h
dali/internal/event/common/scene-impl.cpp
dali/internal/event/common/scene-impl.h
dali/internal/update/common/scene-graph-scene.cpp
dali/internal/update/common/scene-graph-scene.h

index b52e2c2..3399686 100644 (file)
@@ -248,6 +248,10 @@ bool DummyTouchCallback( Actor actor, const TouchEvent& touch )
   return true;
 }
 
+void FrameCallback( int frameId )
+{
+}
+
 } // unnamed namespace
 
 int UtcDaliSceneAdd(void)
@@ -1215,3 +1219,44 @@ int UtcDaliSceneEmptySceneRendering(void)
 
   END_TEST;
 }
+
+int UtcDaliSceneFrameRenderedPresentedCallback(void)
+{
+  tet_infoline( "UtcDaliSceneFrameRenderedCallback" );
+
+  TestApplication application;
+
+  // Add a Renderer
+  Geometry geometry = CreateQuadGeometry();
+  Shader shader = CreateShader();
+  Renderer renderer = Renderer::New( geometry, shader );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer( renderer );
+  Stage::GetCurrent().Add( actor );
+
+  Dali::Integration::Scene scene = application.GetScene();
+
+  int frameId = 1;
+  scene.AddFrameRenderedCallback( std::unique_ptr< CallbackBase >( MakeCallback( &FrameCallback ) ), frameId );
+  scene.AddFramePresentedCallback( std::unique_ptr< CallbackBase >( MakeCallback( &FrameCallback ) ), frameId );
+
+  // Render
+  application.SendNotification();
+  application.Render();
+
+  Dali::Integration::Scene::FrameCallbackContainer callbackContainer;
+  scene.GetFrameRenderedCallback( callbackContainer );
+
+  DALI_TEST_EQUALS( callbackContainer.size(), 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( callbackContainer[0].second, frameId, TEST_LOCATION );
+
+  callbackContainer.clear();
+
+  scene.GetFramePresentedCallback( callbackContainer );
+
+  DALI_TEST_EQUALS( callbackContainer.size(), 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( callbackContainer[0].second, frameId, TEST_LOCATION );
+
+  END_TEST;
+}
index c8bc91b..4ab7dbf 100644 (file)
@@ -149,6 +149,26 @@ void Scene::ProcessEvents()
   GetImplementation(*this).ProcessEvents();
 }
 
+void Scene::AddFrameRenderedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId )
+{
+  GetImplementation( *this ).AddFrameRenderedCallback( std::move( callback ), frameId );
+}
+
+void Scene::AddFramePresentedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId )
+{
+  GetImplementation( *this ).AddFramePresentedCallback( std::move( callback ), frameId );
+}
+
+void Scene::GetFrameRenderedCallback( FrameCallbackContainer& callbacks )
+{
+  GetImplementation( *this ).GetFrameRenderedCallback( callbacks );
+}
+
+void Scene::GetFramePresentedCallback( FrameCallbackContainer& callbacks )
+{
+  GetImplementation( *this ).GetFramePresentedCallback( callbacks );
+}
+
 Scene::EventProcessingFinishedSignalType& Scene::EventProcessingFinishedSignal()
 {
   return GetImplementation(*this).EventProcessingFinishedSignal();
index 9211ae1..7d54eb9 100755 (executable)
  *
  */
 
+// EXTERNAL INCLUDES
+#include <memory>
+
 // INTERNAL INCLUDES
 #include <dali/public-api/object/handle.h>
 #include <dali/public-api/math/vector2.h>
 #include <dali/public-api/math/vector4.h>
+#include <dali/public-api/common/vector-wrapper.h>
 
 namespace Dali
 {
@@ -58,6 +62,8 @@ public:
   typedef Signal< void (const Dali::TouchData&) > TouchSignalType; ///< Touch signal type
   typedef Signal< void (const Dali::WheelEvent&) > WheelEventSignalType; ///< Touched signal type
 
+  using FrameCallbackContainer = std::vector< std::pair< std::unique_ptr< CallbackBase >, int32_t > >;
+
   /**
    * @brief Create an initialized Scene handle.
    *
@@ -230,6 +236,56 @@ public:
   void ProcessEvents();
 
   /**
+   * @brief Adds a callback that is called when the frame rendering is done by the graphics driver.
+   *
+   * @param[in] callback The function to call
+   * @param[in] frameId The Id to specify the frame. It will be passed when the callback is called.
+   *
+   * @note A callback of the following type may be used:
+   * @code
+   *   void MyFunction( int frameId );
+   * @endcode
+   * This callback will be deleted once it is called.
+   *
+   * @note Ownership of the callback is passed onto this class.
+   */
+  void AddFrameRenderedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId );
+
+  /**
+   * @brief Adds a callback that is called when the frame is displayed on the display.
+   *
+   * @param[in] callback The function to call
+   * @param[in] frameId The Id to specify the frame. It will be passed when the callback is called.
+   *
+   * @note A callback of the following type may be used:
+   * @code
+   *   void MyFunction( int frameId );
+   * @endcode
+   * This callback will be deleted once it is called.
+   *
+   * @note Ownership of the callback is passed onto this class.
+   */
+  void AddFramePresentedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId );
+
+  /**
+   * @brief Gets the callback list that is called when the frame rendering is done by the graphics driver.
+   *
+   * @param[out] callbacks The callback list
+   *
+   * @note This is called in the update thread.
+   */
+  void GetFrameRenderedCallback( FrameCallbackContainer& callbacks );
+
+  /**
+   * @brief Gets the callback list that is called when the frame is displayed on the display.
+   *
+   * @param[out] callbacks The callback list
+   *
+   * @note This is called in the update thread.
+   */
+  void GetFramePresentedCallback( FrameCallbackContainer& callbacks );
+
+  /**
    * @brief This signal is emitted just after the event processing is finished.
    *
    * @return The signal to connect to
index d7b80d6..acb362d 100644 (file)
@@ -337,6 +337,28 @@ void Scene::EmitWheelEventSignal(const WheelEvent& event)
   }
 }
 
+void Scene::AddFrameRenderedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId )
+{
+  ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
+  AddFrameRenderedCallbackMessage( tls->GetEventThreadServices(), *mSceneObject, callback.release(), frameId );
+}
+
+void Scene::AddFramePresentedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId )
+{
+  ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
+  AddFramePresentedCallbackMessage( tls->GetEventThreadServices(), *mSceneObject, callback.release(), frameId );
+}
+
+void Scene::GetFrameRenderedCallback( Dali::Integration::Scene::FrameCallbackContainer& callbacks )
+{
+  mSceneObject->GetFrameRenderedCallback( callbacks );
+}
+
+void Scene::GetFramePresentedCallback( Dali::Integration::Scene::FrameCallbackContainer& callbacks )
+{
+  mSceneObject->GetFramePresentedCallback( callbacks );
+}
+
 Integration::Scene::KeyEventSignalType& Scene::KeyEventSignal()
 {
   return mKeyEventSignal;
index 99a3e50..fbf22b2 100644 (file)
@@ -217,6 +217,26 @@ public:
   void EmitWheelEventSignal( const WheelEvent& event );
 
   /**
+   * @copydoc Dali::Integration::Scene::AddFrameRenderedCallback
+   */
+  void AddFrameRenderedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId );
+
+  /**
+   * @copydoc Dali::Integration::Scene::AddFramePresentedCallback
+   */
+  void AddFramePresentedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId );
+
+  /**
+   * @copydoc Dali::Integration::Scene::GetFrameRenderedCallback
+   */
+  void GetFrameRenderedCallback( Dali::Integration::Scene::FrameCallbackContainer& callbacks );
+
+  /**
+   * @copydoc Dali::Integration::Scene::GetFramePresentedCallback
+   */
+  void GetFramePresentedCallback( Dali::Integration::Scene::FrameCallbackContainer& callbacks );
+
+  /**
    * @copydoc Integration::Scene::KeyEventSignal()
    */
   Integration::Scene::KeyEventSignalType& KeyEventSignal();
index 0540516..7f9bf31 100644 (file)
@@ -27,7 +27,9 @@ namespace SceneGraph
 {
 
 Scene::Scene()
-: mContext( nullptr )
+: mContext( nullptr ),
+  mFrameRenderedCallbacks(),
+  mFramePresentedCallbacks()
 {
 }
 
@@ -40,6 +42,9 @@ Scene::~Scene()
     delete mContext;
     mContext = nullptr;
   }
+
+  mFrameRenderedCallbacks.clear();
+  mFramePresentedCallbacks.clear();
 }
 
 void Scene::GlContextDestroyed()
@@ -75,6 +80,38 @@ RenderInstructionContainer& Scene::GetRenderInstructions()
   return mInstructions;
 }
 
+void Scene::AddFrameRenderedCallback( CallbackBase* callback, int32_t frameId )
+{
+  mFrameRenderedCallbacks.push_back( std::make_pair( std::unique_ptr< CallbackBase >( callback ), frameId ) );
+}
+
+void Scene::AddFramePresentedCallback( CallbackBase* callback, int32_t frameId )
+{
+  mFramePresentedCallbacks.push_back( std::make_pair( std::unique_ptr< CallbackBase >( callback ), frameId ) );
+}
+
+void Scene::GetFrameRenderedCallback( Dali::Integration::Scene::FrameCallbackContainer& callbacks )
+{
+  // Transfer owership of the callbacks
+  for( auto&& iter : mFrameRenderedCallbacks )
+  {
+    callbacks.push_back( std::make_pair( std::move( iter.first ), iter.second ) );
+  }
+
+  mFrameRenderedCallbacks.clear();
+}
+
+void Scene::GetFramePresentedCallback( Dali::Integration::Scene::FrameCallbackContainer& callbacks )
+{
+  // Transfer owership of the callbacks
+  for( auto&& iter : mFramePresentedCallbacks )
+  {
+    callbacks.push_back( std::make_pair( std::move( iter.first ), iter.second ) );
+  }
+
+  mFramePresentedCallbacks.clear();
+}
+
 } //SceneGraph
 
 } //Internal
index 221c42e..a94becc 100644 (file)
 // INTERNAL INCLUDES
 #include <dali/integration-api/scene.h>
 #include <dali/integration-api/gl-defines.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
 #include <dali/internal/render/gl-resources/context.h>
 #include <dali/internal/render/common/render-instruction-container.h>
+#include <dali/public-api/common/vector-wrapper.h>
 
 namespace Dali
 {
@@ -73,6 +76,52 @@ public:
    */
   RenderInstructionContainer& GetRenderInstructions();
 
+  /**
+   * @brief Adds a callback that is called when the frame rendering is done by the graphics driver.
+   *
+   * @param[in] callback The function to call
+   * @param[in] frameId The Id to specify the frame. It will be passed when the callback is called.
+   *
+   * @note A callback of the following type may be used:
+   * @code
+   *   void MyFunction( int frameId );
+   * @endcode
+   * This callback will be deleted once it is called.
+   *
+   * @note Ownership of the callback is passed onto this class.
+   */
+  void AddFrameRenderedCallback( CallbackBase* callback, int32_t frameId );
+
+  /**
+   * @brief Adds a callback that is called when the frame is displayed on the display.
+   *
+   * @param[in] callback The function to call
+   * @param[in] frameId The Id to specify the frame. It will be passed when the callback is called.
+   *
+   * @note A callback of the following type may be used:
+   * @code
+   *   void MyFunction( int frameId );
+   * @endcode
+   * This callback will be deleted once it is called.
+   *
+   * @note Ownership of the callback is passed onto this class.
+   */
+  void AddFramePresentedCallback( CallbackBase* callback, int32_t frameId );
+
+  /**
+   * @brief Gets the callback list that is called when the frame rendering is done by the graphics driver.
+   *
+   * @param[out] callbacks The callback list
+   */
+  void GetFrameRenderedCallback( Dali::Integration::Scene::FrameCallbackContainer& callbacks );
+
+  /**
+   * @brief Gets the callback list that is called when the frame is displayed on the display.
+   *
+   * @param[out] callbacks The callback list
+   */
+  void GetFramePresentedCallback( Dali::Integration::Scene::FrameCallbackContainer& callbacks );
+
 private:
 
   Context*                    mContext;   ///< The context holding the GL state of rendering for the scene
@@ -81,8 +130,33 @@ private:
   // Update manager updates instructions for the next frame while we render the current one
 
   RenderInstructionContainer  mInstructions;   ///< Render instructions for the scene
+
+  Dali::Integration::Scene::FrameCallbackContainer mFrameRenderedCallbacks;   ///< Frame rendered callbacks
+  Dali::Integration::Scene::FrameCallbackContainer mFramePresentedCallbacks;  ///< Frame presented callbacks
 };
 
+/// Messages
+inline void AddFrameRenderedCallbackMessage( EventThreadServices& eventThreadServices, const Scene& scene, const CallbackBase* callback, int32_t frameId )
+{
+  typedef MessageValue2< Scene, CallbackBase*, int32_t > LocalType;
+
+  // Reserve some memory inside the message queue
+  uint32_t* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &scene, &Scene::AddFrameRenderedCallback, const_cast< CallbackBase* >( callback ), frameId );
+}
+
+inline void AddFramePresentedCallbackMessage( EventThreadServices& eventThreadServices, const Scene& scene, const CallbackBase* callback, int32_t frameId )
+{
+  typedef MessageValue2< Scene, CallbackBase*, int32_t > LocalType;
+
+  // Reserve some memory inside the message queue
+  uint32_t* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &scene, &Scene::AddFramePresentedCallback, const_cast< CallbackBase* >( callback ), frameId );
+}
 
 } // namespace SceneGraph