/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
// INTERNAL INCLUDES
#include <dali/integration-api/adaptor-framework/thread-synchronization-interface.h>
-#include <dali/integration-api/adaptor-framework/trigger-event-factory-interface.h>
+#include <dali/integration-api/adaptor-framework/trigger-event-factory.h>
#include <dali/internal/adaptor/common/adaptor-impl.h>
#include <dali/internal/adaptor/common/adaptor-internal-services.h>
#include <dali/internal/graphics/gles/egl-graphics.h>
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 ),
{
delete mRotationTrigger;
}
-
- if ( mEGLSurface )
- {
- DestroySurface();
- }
}
void WindowRenderSurface::Initialize( Any surface )
// Default window size == screen size
mPositionSize.x = 0;
mPositionSize.y = 0;
-
WindowSystem::GetScreenSize( mPositionSize.width, mPositionSize.height );
}
if( !mRotationTrigger )
{
- TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
- mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
+ mRotationTrigger = TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
}
mPositionSize.width = width;
void WindowRenderSurface::InitializeGraphics()
{
-
mGraphics = &mAdaptor->GetGraphicsInterface();
+ DALI_ASSERT_ALWAYS( mGraphics && "Graphics interface is not created" );
+
auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
mEGL = &eglGraphics->GetEglInterface();
// Check rotation capability
mRotationSupported = mWindowBase->IsEglWindowRotationSupported();
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::CreateSurface: w = %d h = %d angle = %d screen rotation = %d\n",
- mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
+ DALI_LOG_RELEASE_INFO("WindowRenderSurface::CreateSurface: WinId (%d), w = %d h = %d angle = %d screen rotation = %d\n",
+ mWindowBase->GetNativeWindowId(), mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
}
void WindowRenderSurface::DestroySurface()
DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
+ if( eglGraphics )
+ {
+ DALI_LOG_RELEASE_INFO("WindowRenderSurface::DestroySurface: WinId (%d)\n", mWindowBase->GetNativeWindowId() );
- Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
- eglImpl.DestroySurface( mEGLSurface );
+ Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
- mWindowBase->DestroyEglWindow();
+ eglImpl.DestroySurface( mEGLSurface );
+ mEGLSurface = nullptr;
+
+ // Destroy context also
+ eglImpl.DestroyContext( mEGLContext );
+ mEGLContext = nullptr;
+
+ mWindowBase->DestroyEglWindow();
+ }
}
bool WindowRenderSurface::ReplaceGraphicsSurface()
{
}
-bool WindowRenderSurface::PreRender( bool resizingSurface )
+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);
+
if( resizingSurface )
{
// Window rotate or screen rotate
DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
}
+
+ if (eglGraphics)
+ {
+ Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+ eglImpl.SetFullSwapNextFrame();
+ }
}
- auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
- if ( eglGraphics )
+ if (eglGraphics)
{
- GlImplementation& mGLES = eglGraphics->GetGlesInterface();
- mGLES.PreRender();
+ Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+ eglImpl.SetDamage( mEGLSurface, damagedRects, clippingRect );
}
return true;
}
-void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
+void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects )
{
// Inform the gl implementation that rendering has finished before informing the surface
auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
{
if( !mRotationFinished )
{
- DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PostRender: Trigger rotation event\n" );
+ if( mThreadSynchronization )
+ {
+ // Enable PostRender flag
+ mThreadSynchronization->PostRenderStarted();
+ }
+
+ DALI_LOG_RELEASE_INFO("WindowRenderSurface::PostRender: Trigger rotation event\n" );
mRotationTrigger->Trigger();
}
Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
- eglImpl.SwapBuffers( mEGLSurface );
+ eglImpl.SwapBuffers( mEGLSurface, damagedRects );
if( mRenderNotification )
{
// Nothing to do.
}
-Integration::RenderSurface::Type WindowRenderSurface::GetSurfaceType()
+Dali::RenderSurfaceInterface::Type WindowRenderSurface::GetSurfaceType()
{
- return RenderSurface::WINDOW_RENDER_SURFACE;
+ return Dali::RenderSurfaceInterface::WINDOW_RENDER_SURFACE;
}
void WindowRenderSurface::MakeContextCurrent()
}
}
+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