From b1920196706cf4ff38badfa297d91be3f9342dc5 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Mon, 15 Jun 2020 16:35:01 +0900 Subject: [PATCH] (Scene) Add frame rendered/presented callback Change-Id: Ic903229e71d76a05a0af24a68b26440d26462fa6 --- automated-tests/src/dali/utc-Dali-Scene.cpp | 45 ++++++++++++++ dali/integration-api/scene.cpp | 20 ++++++ dali/integration-api/scene.h | 56 +++++++++++++++++ dali/internal/event/common/scene-impl.cpp | 22 +++++++ dali/internal/event/common/scene-impl.h | 20 ++++++ dali/internal/update/common/scene-graph-scene.cpp | 39 +++++++++++- dali/internal/update/common/scene-graph-scene.h | 74 +++++++++++++++++++++++ 7 files changed, 275 insertions(+), 1 deletion(-) diff --git a/automated-tests/src/dali/utc-Dali-Scene.cpp b/automated-tests/src/dali/utc-Dali-Scene.cpp index 3f409fe..0b6ef44 100644 --- a/automated-tests/src/dali/utc-Dali-Scene.cpp +++ b/automated-tests/src/dali/utc-Dali-Scene.cpp @@ -248,6 +248,10 @@ bool DummyTouchCallback( Actor actor, const TouchEvent& touch ) return true; } +void FrameCallback( int frameId ) +{ +} + } // unnamed namespace int UtcDaliSceneAdd(void) @@ -1216,3 +1220,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; +} diff --git a/dali/integration-api/scene.cpp b/dali/integration-api/scene.cpp index c8bc91b..4ab7dbf 100644 --- a/dali/integration-api/scene.cpp +++ b/dali/integration-api/scene.cpp @@ -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(); diff --git a/dali/integration-api/scene.h b/dali/integration-api/scene.h index 9211ae1..7d54eb9 100755 --- a/dali/integration-api/scene.h +++ b/dali/integration-api/scene.h @@ -18,10 +18,14 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include #include +#include 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 diff --git a/dali/internal/event/common/scene-impl.cpp b/dali/internal/event/common/scene-impl.cpp index d7b80d6..acb362d 100644 --- a/dali/internal/event/common/scene-impl.cpp +++ b/dali/internal/event/common/scene-impl.cpp @@ -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; diff --git a/dali/internal/event/common/scene-impl.h b/dali/internal/event/common/scene-impl.h index 99a3e50..fbf22b2 100644 --- a/dali/internal/event/common/scene-impl.h +++ b/dali/internal/event/common/scene-impl.h @@ -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(); diff --git a/dali/internal/update/common/scene-graph-scene.cpp b/dali/internal/update/common/scene-graph-scene.cpp index 0540516..7f9bf31 100644 --- a/dali/internal/update/common/scene-graph-scene.cpp +++ b/dali/internal/update/common/scene-graph-scene.cpp @@ -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 diff --git a/dali/internal/update/common/scene-graph-scene.h b/dali/internal/update/common/scene-graph-scene.h index 221c42e..a94becc 100644 --- a/dali/internal/update/common/scene-graph-scene.h +++ b/dali/internal/update/common/scene-graph-scene.h @@ -20,8 +20,11 @@ // INTERNAL INCLUDES #include #include +#include +#include #include #include +#include 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 -- 2.7.4