GetImplementation(window).SetDamagedAreas(areas);
}
+void AddFrameRenderedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId )
+{
+ GetImplementation( window ).AddFrameRenderedCallback( std::move( callback ), frameId );
+}
+
+void AddFramePresentedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId )
+{
+ GetImplementation( window ).AddFramePresentedCallback( std::move( callback ), frameId );
+}
+
} // namespace DevelWindow
} // namespace Dali
*/
// EXTERNAL INCLUDES
+#include <memory>
// INTERNAL INCLUDES
#include <dali/public-api/common/vector-wrapper.h>
*/
DALI_ADAPTOR_API void SetDamagedAreas(Window window, std::vector<Dali::Rect<int>>& areas);
+/**
+ * @brief Adds a callback that is called when the frame rendering is done by the graphics driver.
+ *
+ * @param[in] window The window instance
+ * @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.
+ */
+DALI_ADAPTOR_API void AddFrameRenderedCallback( Window window, 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] window The window instance
+ * @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.
+ */
+DALI_ADAPTOR_API void AddFramePresentedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId );
+
} // namespace DevelWindow
} // namespace Dali
class DisplayConnection;
class ThreadSynchronizationInterface;
+namespace Integration
+{
+class Scene;
+}
+
namespace Internal
{
namespace Adaptor
: mAdaptor( nullptr ),
mGraphics( nullptr ),
mDisplayConnection( nullptr ),
+ mScene( nullptr ),
mDepthBufferRequired( Integration::DepthBufferAvailable::FALSE ),
mStencilBufferRequired( Integration::StencilBufferAvailable::FALSE )
{}
mDisplayConnection = &displayConnection;
}
+ /**
+ * @brief Sets a Scene that is rendered on this surface.
+ * @param scene The Scene object
+ */
+ void SetScene( Dali::Integration::Scene& scene )
+ {
+ // This will be changed to use the WeakHandle later.
+ mScene = &scene;
+ }
+
private:
/**
Dali::Internal::Adaptor::AdaptorInternalServices* mAdaptor;
Dali::Internal::Adaptor::GraphicsInterface* mGraphics;
Dali::DisplayConnection* mDisplayConnection;
+ Dali::Integration::Scene* mScene;
private:
{
#if defined(DEBUG_ENABLED)
-Integration::Log::Filter* gTouchEventLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_TOUCH");
+Debug::Filter* gSceneHolderLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_SCENE_HOLDER" );
#endif
// Copied from x server
mScene.SetDpi( Vector2( static_cast<float>( dpiHorizontal ), static_cast<float>( dpiVertical ) ) );
mSurface->SetAdaptor( *mAdaptor );
+ mSurface->SetScene( mScene );
OnSurfaceSet( surface );
}
mScene.SetDpi( Vector2( static_cast<float>( dpiHorizontal ), static_cast<float>( dpiVertical ) ) );
mSurface->SetAdaptor( *mAdaptor );
+ mSurface->SetScene( mScene );
}
OnAdaptorSet( adaptor );
Integration::TouchEventCombiner::EventDispatchType type = mCombiner.GetNextTouchEvent(point, timeStamp, touchEvent, hoverEvent);
if( type != Integration::TouchEventCombiner::DispatchNone )
{
- DALI_LOG_INFO( gTouchEventLogFilter, Debug::General, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.GetDeviceId(), point.GetState(), point.GetScreenPosition().x, point.GetScreenPosition().y );
+ DALI_LOG_INFO( gSceneHolderLogFilter, Debug::Verbose, "%d: Device %d: Button state %d (%.2f, %.2f)\n", timeStamp, point.GetDeviceId(), point.GetState(), point.GetScreenPosition().x, point.GetScreenPosition().y );
// Signals can be emitted while processing core events, and the scene holder could be deleted in the signal callback.
// Keep the handle alive until the core events are processed.
mAdaptor->ProcessCoreEvents();
}
+void SceneHolder::AddFrameRenderedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId )
+{
+ mScene.AddFrameRenderedCallback( std::move( callback ), frameId );
+
+ DALI_LOG_INFO( gSceneHolderLogFilter, Debug::General, "SceneHolder::AddFrameRenderedCallback:: Added [%d]\n", frameId );
+}
+
+void SceneHolder::AddFramePresentedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId )
+{
+ mScene.AddFramePresentedCallback( std::move( callback ), frameId );
+
+ DALI_LOG_INFO( gSceneHolderLogFilter, Debug::General, "SceneHolder::AddFramePresentedCallback:: Added [%d]\n", frameId );
+}
+
Dali::Integration::SceneHolder SceneHolder::Get( Dali::Actor actor )
{
SceneHolder* sceneHolderImpl = nullptr;
void FeedKeyEvent( Dali::Integration::KeyEvent& keyEvent );
/**
+ * @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 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 AddFramePresentedCallback( std::unique_ptr< CallbackBase > callback, int32_t frameId );
+
+ /**
* @copydoc Dali::Integration::SceneHolder::Get()
*/
static Dali::Integration::SceneHolder Get( Dali::Actor actor );
// if there is an event, execute the callback
if( type != FileDescriptorMonitor::FD_NO_EVENT )
{
- CallbackBase::Execute( *impl->mCallback, static_cast< FileDescriptorMonitor::EventType >( type ) );
+ CallbackBase::Execute( *impl->mCallback, static_cast< FileDescriptorMonitor::EventType >( type ), impl->mFileDescriptor );
}
return 1; // Continue receiving callbacks
* mFileDescriptorMonitor = new FileDescriptorMonitor( myFd, MakeCallback( this, &MyClass::FdCallback ), FileDescriptorMonitor::FD_READABLE );
* }
*
- * void MyClass::FdCallback( EventType event )
+ * void MyClass::FdCallback( EventType event, int fileDescriptor )
* {
* if( event & FileDescriptorMonitor::FD_ERROR)
* {
}
}
-void TriggerEvent::Triggered( FileDescriptorMonitor::EventType eventBitMask )
+void TriggerEvent::Triggered( FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor )
{
if( !( eventBitMask & FileDescriptorMonitor::FD_READABLE ) )
{
/**
* @brief Called when our event file descriptor has been written to.
* @param[in] eventBitMask bit mask of events that occured on the file descriptor
+ * @param[in] fileDescriptor The file descriptor
*/
- void Triggered( FileDescriptorMonitor::EventType eventBitMask );
+ void Triggered( FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor );
private:
if( ecore_main_fd_handler_active_get( handler, ECORE_FD_ERROR) )
{
- CallbackBase::Execute( *impl->mCallback, FileDescriptorMonitor::FD_ERROR);
+ CallbackBase::Execute( *impl->mCallback, FileDescriptorMonitor::FD_ERROR, impl->mFileDescriptor );
DALI_LOG_ERROR("ECORE_FD_ERROR occurred on %d\n", impl->mFileDescriptor);
return ECORE_CALLBACK_CANCEL;
// if there is an event, execute the callback
if( type != FileDescriptorMonitor::FD_NO_EVENT )
{
- CallbackBase::Execute( *impl->mCallback, static_cast< FileDescriptorMonitor::EventType >(type ) );
+ CallbackBase::Execute( *impl->mCallback, static_cast< FileDescriptorMonitor::EventType >(type ), impl->mFileDescriptor );
}
return ECORE_CALLBACK_RENEW;
{
}
+int WindowBaseAndroid::CreateFrameRenderedSyncFence()
+{
+ return -1;
+}
+
+int WindowBaseAndroid::CreateFramePresentedSyncFence()
+{
+ return -1;
+}
+
} // namespace Adaptor
} // namespace Internal
*/
virtual void SetParent( WindowBase* parentWinBase ) override;
+ /**
+ * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence()
+ */
+ virtual int CreateFrameRenderedSyncFence() override;
+
+ /**
+ * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence()
+ */
+ virtual int CreateFramePresentedSyncFence() override;
+
private:
/**
*/
virtual void SetParent( WindowBase* parentWinBase ) = 0;
+ /**
+ * @brief Create a sync fence that can tell the frame is rendered by the graphics driver.
+ * @return The file descriptor that tells when it is rendered.
+ */
+ virtual int CreateFrameRenderedSyncFence() = 0;
+
+ /**
+ * @brief Create a sync fence that can tell the frame is presented by the display server.
+ * @return The file descriptor that tells when it is presented.
+ */
+ virtual int CreateFramePresentedSyncFence() = 0;
+
// Signals
/**
mThreadSynchronization( NULL ),
mRenderNotification( NULL ),
mRotationTrigger( NULL ),
+ mFrameRenderedTrigger(),
mGraphics( nullptr ),
mEGLSurface( nullptr ),
mEGLContext( nullptr ),
mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
mOutputTransformedSignal(),
+ mFrameCallbackInfoContainer(),
mRotationAngle( 0 ),
mScreenRotationAngle( 0 ),
mOwnSurface( false ),
bool WindowRenderSurface::PreRender( bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect )
{
+ Dali::Integration::Scene::FrameCallbackContainer callbacks;
+
+ if( mScene )
+ {
+ mScene->GetFrameRenderedCallback( callbacks );
+ if( !callbacks.empty() )
+ {
+ int frameRenderedSync = mWindowBase->CreateFrameRenderedSyncFence();
+ if( frameRenderedSync != -1 )
+ {
+ DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: CreateFrameRenderedSyncFence [%d]\n", frameRenderedSync );
+
+ mFrameCallbackInfoContainer.push_back( std::unique_ptr< FrameCallbackInfo >( new FrameCallbackInfo( callbacks, frameRenderedSync ) ) );
+
+ if( !mFrameRenderedTrigger )
+ {
+ mFrameRenderedTrigger = std::unique_ptr< TriggerEventInterface >( TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessFrameCallback ),
+ TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ) );
+ }
+ mFrameRenderedTrigger->Trigger();
+ }
+ else
+ {
+ DALI_LOG_ERROR( "WindowRenderSurface::PreRender: CreateFrameRenderedSyncFence is failed\n" );
+ }
+
+ // Clear callbacks
+ callbacks.clear();
+ }
+
+ mScene->GetFramePresentedCallback( callbacks );
+ if( !callbacks.empty() )
+ {
+ int framePresentedSync = mWindowBase->CreateFramePresentedSyncFence();
+ if( framePresentedSync != -1 )
+ {
+ DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: CreateFramePresentedSyncFence [%d]\n", framePresentedSync );
+
+ mFrameCallbackInfoContainer.push_back( std::unique_ptr< FrameCallbackInfo >( new FrameCallbackInfo( callbacks, framePresentedSync ) ) );
+
+ if( !mFrameRenderedTrigger )
+ {
+ mFrameRenderedTrigger = std::unique_ptr< TriggerEventInterface >( TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessFrameCallback ),
+ TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ) );
+ }
+ mFrameRenderedTrigger->Trigger();
+ }
+ else
+ {
+ DALI_LOG_ERROR( "WindowRenderSurface::PreRender: CreateFramePresentedSyncFence is failed\n" );
+ }
+
+ // Clear callbacks
+ callbacks.clear();
+ }
+ }
+
MakeContextCurrent();
auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
}
}
+void WindowRenderSurface::ProcessFrameCallback()
+{
+ for( auto&& iter : mFrameCallbackInfoContainer )
+ {
+ if( !iter->fileDescriptorMonitor )
+ {
+ iter->fileDescriptorMonitor = std::unique_ptr< FileDescriptorMonitor >( new FileDescriptorMonitor( iter->fileDescriptor,
+ MakeCallback( this, &WindowRenderSurface::OnFileDescriptorEventDispatched ), FileDescriptorMonitor::FD_READABLE ) );
+
+ DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::ProcessFrameCallback: Add handler [%d]\n", iter->fileDescriptor );
+ }
+ }
+}
+
+void WindowRenderSurface::OnFileDescriptorEventDispatched( FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor )
+{
+ if( !( eventBitMask & FileDescriptorMonitor::FD_READABLE ) )
+ {
+ DALI_LOG_ERROR( "WindowRenderSurface::OnFileDescriptorEventDispatched: file descriptor error [%d]\n", eventBitMask );
+ close( fileDescriptor );
+ return;
+ }
+
+ DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OnFileDescriptorEventDispatched: Frame rendered [%d]\n", fileDescriptor );
+
+ auto frameCallbackInfo = std::find_if( mFrameCallbackInfoContainer.begin(), mFrameCallbackInfoContainer.end(),
+ [fileDescriptor]( std::unique_ptr< FrameCallbackInfo >& callbackInfo )
+ {
+ return callbackInfo->fileDescriptor == fileDescriptor;
+ } );
+ if( frameCallbackInfo != mFrameCallbackInfoContainer.end() )
+ {
+ // Call the connected callback
+ for( auto&& iter : ( *frameCallbackInfo )->callbacks )
+ {
+ CallbackBase::Execute( *( iter.first ), iter.second );
+ }
+ mFrameCallbackInfoContainer.erase( frameCallbackInfo );
+ }
+}
+
} // namespace Adaptor
} // namespace internal
// EXTERNAL INCLUDES
#include <dali/public-api/signals/connection-tracker.h>
#include <dali/public-api/signals/dali-signal.h>
+#include <dali/integration-api/scene.h>
+#include <unistd.h>
// INTERNAL INCLUDES
#include <dali/integration-api/adaptor-framework/egl-interface.h>
#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
#include <dali/internal/graphics/common/graphics-interface.h>
+#include <dali/internal/system/common/file-descriptor-monitor.h>
namespace Dali
{
*/
void ProcessRotationRequest();
+ /**
+ * @brief Used as the callback for the frame rendered / presented.
+ */
+ void ProcessFrameCallback();
+
+ /**
+ * @brief Called when our event file descriptor has been written to.
+ * @param[in] eventBitMask bit mask of events that occured on the file descriptor
+ * @param[in] fileDescriptor The file descriptor
+ */
+ void OnFileDescriptorEventDispatched( FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor );
+
protected:
// Undefined
// Undefined
WindowRenderSurface& operator=(const WindowRenderSurface& rhs) = delete;
+private:
+
+ struct FrameCallbackInfo
+ {
+ FrameCallbackInfo( Dali::Integration::Scene::FrameCallbackContainer& callbackList, int fd )
+ : callbacks(),
+ fileDescriptorMonitor(),
+ fileDescriptor( fd )
+ {
+ // Transfer owership of the CallbackBase
+ for( auto&& iter : callbackList )
+ {
+ callbacks.push_back( std::make_pair( std::move( iter.first ), iter.second ) );
+ }
+ }
+
+ ~FrameCallbackInfo()
+ {
+ // Delete FileDescriptorMonitor before close fd.
+ fileDescriptorMonitor.release();
+ close( fileDescriptor );
+ }
+
+ Dali::Integration::Scene::FrameCallbackContainer callbacks;
+ std::unique_ptr< FileDescriptorMonitor > fileDescriptorMonitor;
+ int fileDescriptor;
+ };
+
+ using FrameCallbackInfoContainer = std::vector< std::unique_ptr< FrameCallbackInfo > >;
+
private: // Data
EglInterface* mEGL;
ThreadSynchronizationInterface* mThreadSynchronization;
TriggerEventInterface* mRenderNotification; ///< Render notification trigger
TriggerEventInterface* mRotationTrigger;
+ std::unique_ptr< TriggerEventInterface > mFrameRenderedTrigger;
GraphicsInterface* mGraphics; ///< Graphics interface
EGLSurface mEGLSurface;
EGLContext mEGLContext;
ColorDepth mColorDepth; ///< Color depth of surface (32 bit or 24 bit)
OutputSignalType mOutputTransformedSignal;
+ FrameCallbackInfoContainer mFrameCallbackInfoContainer;
int mRotationAngle;
int mScreenRotationAngle;
bool mOwnSurface; ///< Whether we own the surface (responsible for deleting it)
ecore_wl_window_parent_set( mEcoreWindow, ecoreParent );
}
+int WindowBaseEcoreWl::CreateFrameRenderedSyncFence()
+{
+ return -1;
+}
+
+int WindowBaseEcoreWl::CreateFramePresentedSyncFence()
+{
+ return -1;
+}
+
} // namespace Adaptor
} // namespace Internal
*/
virtual void SetParent( WindowBase* parentWinBase ) override;
+ /**
+ * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence()
+ */
+ virtual int CreateFrameRenderedSyncFence() override;
+
+ /**
+ * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence()
+ */
+ virtual int CreateFramePresentedSyncFence() override;
+
private:
/**
ecore_wl2_window_parent_set( mEcoreWindow, ecoreParent );
}
+int WindowBaseEcoreWl2::CreateFrameRenderedSyncFence()
+{
+ return wl_egl_window_tizen_create_commit_sync_fd( mEglWindow );
+}
+
+int WindowBaseEcoreWl2::CreateFramePresentedSyncFence()
+{
+ return wl_egl_window_tizen_create_presentation_sync_fd( mEglWindow );
+}
+
} // namespace Adaptor
} // namespace Internal
*/
virtual void SetParent( WindowBase* parentWinBase ) override;
+ /**
+ * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence()
+ */
+ virtual int CreateFrameRenderedSyncFence() override;
+
+ /**
+ * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence()
+ */
+ virtual int CreateFramePresentedSyncFence() override;
+
private:
/**
}
}
+int WindowBaseEcoreX::CreateFrameRenderedSyncFence()
+{
+ return -1;
+}
+
+int WindowBaseEcoreX::CreateFramePresentedSyncFence()
+{
+ return -1;
+}
+
} // namespace Adaptor
} // namespace Internal
*/
virtual void SetParent( WindowBase* parentWinBase ) override;
+ /**
+ * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence()
+ */
+ virtual int CreateFrameRenderedSyncFence() override;
+
+ /**
+ * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence()
+ */
+ virtual int CreateFramePresentedSyncFence() override;
+
private:
/**
}
+int WindowBaseWin::CreateFrameRenderedSyncFence()
+{
+ return -1;
+}
+
+int WindowBaseWin::CreateFramePresentedSyncFence()
+{
+ return -1;
+}
+
} // namespace Adaptor
} // namespace Internal
*/
virtual void SetParent( WindowBase* parentWinBase ) override;
+ /**
+ * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFrameRenderedSyncFence()
+ */
+ virtual int CreateFrameRenderedSyncFence() override;
+
+ /**
+ * @copydoc Dali::Internal::Adaptor::WindowBase::CreateFramePresentedSyncFence()
+ */
+ virtual int CreateFramePresentedSyncFence() override;
+
private:
/**