X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fadaptor%2Fcommon%2Fcombined-update-render-controller.cpp;h=eb2897560fc38d20b61a19d954843631ad554551;hb=d9fbc408f645a0ed6404a23c680bdd74d4d8e490;hp=4b794ce41a4bbf66a28a0c04d6d0c3b818486cea;hpb=3382101c1ce68b0b4f1a3398d977b210bcb58e2f;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git diff --git a/dali/internal/adaptor/common/combined-update-render-controller.cpp b/dali/internal/adaptor/common/combined-update-render-controller.cpp index 4b794ce..eb28975 100644 --- a/dali/internal/adaptor/common/combined-update-render-controller.cpp +++ b/dali/internal/adaptor/common/combined-update-render-controller.cpp @@ -21,6 +21,7 @@ // EXTERNAL INCLUDES #include #include +#include // INTERNAL INCLUDES #include @@ -32,6 +33,7 @@ #include #include #include +#include namespace Dali { @@ -87,11 +89,12 @@ const unsigned int MAXIMUM_UPDATE_REQUESTS = 2; // EVENT THREAD /////////////////////////////////////////////////////////////////////////////////////////////////// -CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions ) +CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions, ThreadMode threadMode ) : mFpsTracker( environmentOptions ), mUpdateStatusLogger( environmentOptions ), mEventThreadSemaphore(), mGraphicsInitializeSemaphore(), + mSurfaceSemaphore(), mUpdateRenderThreadWaitCondition(), mAdaptorInterfaces( adaptorInterfaces ), mPerformanceInterface( adaptorInterfaces.GetPerformanceInterface() ), @@ -107,6 +110,7 @@ CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalS mDefaultHalfFrameNanoseconds( 0u ), mUpdateRequestCount( 0u ), mRunning( FALSE ), + mThreadMode( threadMode ), mUpdateRenderRunCount( 0 ), mDestroyUpdateRenderThread( FALSE ), mUpdateRenderThreadCanSleep( FALSE ), @@ -132,12 +136,12 @@ CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalS currentSurface->SetThreadSynchronization( *this ); } - TriggerEventFactoryInterface& triggerFactory = mAdaptorInterfaces.GetTriggerEventFactoryInterface(); - mSleepTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &CombinedUpdateRenderController::ProcessSleepRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ); + mSleepTrigger = TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &CombinedUpdateRenderController::ProcessSleepRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ); // Initialize to 0 so that it just waits if sem_post has not been called sem_init( &mEventThreadSemaphore, 0, 0 ); sem_init( &mGraphicsInitializeSemaphore, 0, 0 ); + sem_init( &mSurfaceSemaphore, 0, 0 ); } CombinedUpdateRenderController::~CombinedUpdateRenderController() @@ -178,7 +182,7 @@ void CombinedUpdateRenderController::Start() sem_wait( &mEventThreadSemaphore ); } - Integration::RenderSurface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); + Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); if( currentSurface ) { currentSurface->StartRender(); @@ -235,7 +239,7 @@ void CombinedUpdateRenderController::Stop() LOG_EVENT_TRACE; // Stop Rendering and the Update/Render Thread - Integration::RenderSurface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); + Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); if( currentSurface ) { currentSurface->StopRender(); @@ -288,7 +292,7 @@ void CombinedUpdateRenderController::RequestUpdateOnce( UpdateMode updateMode ) ++mUpdateRequestCount; } - if( IsUpdateRenderThreadPaused() ) + if( IsUpdateRenderThreadPaused() || updateMode == UpdateMode::FORCE_RENDER ) { LOG_EVENT_TRACE; @@ -317,7 +321,7 @@ void CombinedUpdateRenderController::ReplaceSurface( Dali::RenderSurfaceInterfac } // Wait until the surface has been replaced - sem_wait( &mEventThreadSemaphore ); + sem_wait( &mSurfaceSemaphore ); LOG_EVENT( "Surface replaced, event-thread continuing" ); } @@ -340,7 +344,7 @@ void CombinedUpdateRenderController::DeleteSurface( Dali::RenderSurfaceInterface } // Wait until the surface has been deleted - sem_wait( &mEventThreadSemaphore ); + sem_wait( &mSurfaceSemaphore ); LOG_EVENT( "Surface deleted, event-thread continuing" ); } @@ -399,6 +403,17 @@ void CombinedUpdateRenderController::SetPreRenderCallback( CallbackBase* callbac mPreRenderCallback = callback; } +void CombinedUpdateRenderController::AddSurface( Dali::RenderSurfaceInterface* surface ) +{ + LOG_EVENT_TRACE; + LOG_EVENT( "Surface is added" ); + if( mUpdateRenderThread ) + { + // Set the ThreadSyncronizationInterface on the added surface + surface->SetThreadSynchronization( *this ); + } +} + /////////////////////////////////////////////////////////////////////////////////////////////////// // EVENT THREAD /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -406,9 +421,31 @@ void CombinedUpdateRenderController::SetPreRenderCallback( CallbackBase* callbac void CombinedUpdateRenderController::RunUpdateRenderThread( int numberOfCycles, AnimationProgression animationProgression, UpdateMode updateMode ) { ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); - mUpdateRenderRunCount = numberOfCycles; + + switch( mThreadMode ) + { + case ThreadMode::NORMAL: + { + mUpdateRenderRunCount = numberOfCycles; + mUseElapsedTimeAfterWait = ( animationProgression == AnimationProgression::USE_ELAPSED_TIME ); + break; + } + case ThreadMode::RUN_IF_REQUESTED: + { + if( updateMode != UpdateMode::FORCE_RENDER ) + { + // Render only if the update mode is FORCE_RENDER which means the application requests it. + // We don't want to awake the update thread. + return; + } + + mUpdateRenderRunCount++; // Increase the update request count + mUseElapsedTimeAfterWait = TRUE; // The elapsed time should be used. We want animations to proceed. + break; + } + } + mUpdateRenderThreadCanSleep = FALSE; - mUseElapsedTimeAfterWait = ( animationProgression == AnimationProgression::USE_ELAPSED_TIME ); mUploadWithoutRendering = ( updateMode == UpdateMode::SKIP_RENDER ); LOG_COUNTER_EVENT( "mUpdateRenderRunCount: %d, mUseElapsedTimeAfterWait: %d", mUpdateRenderRunCount, mUseElapsedTimeAfterWait ); mUpdateRenderThreadWaitCondition.Notify( lock ); @@ -430,6 +467,12 @@ void CombinedUpdateRenderController::StopUpdateRenderThread() bool CombinedUpdateRenderController::IsUpdateRenderThreadPaused() { ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + + if( mThreadMode == ThreadMode::RUN_IF_REQUESTED ) + { + return !mRunning || mUpdateRenderThreadCanSleep; + } + return ( mUpdateRenderRunCount != CONTINUOUS ) || // Report paused if NOT continuously running mUpdateRenderThreadCanSleep; // Report paused if sleeping } @@ -550,7 +593,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() uint64_t currentFrameStartTime = 0; TimeService::GetNanoseconds( currentFrameStartTime ); - const uint64_t timeSinceLastFrame = currentFrameStartTime - lastFrameTime; + uint64_t timeSinceLastFrame = currentFrameStartTime - lastFrameTime; // Optional FPS Tracking when continuously rendering if( useElapsedTime && mFpsTracker.Enabled() ) @@ -565,7 +608,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() // REPLACE SURFACE ////////////////////////////// - Integration::RenderSurface* newSurface = ShouldSurfaceBeReplaced(); + Dali::RenderSurfaceInterface* newSurface = ShouldSurfaceBeReplaced(); if( DALI_UNLIKELY( newSurface ) ) { LOG_UPDATE_RENDER_TRACE_FMT( "Replacing Surface" ); @@ -597,6 +640,16 @@ void CombinedUpdateRenderController::UpdateRenderThread() float frameDelta = 0.0f; if( useElapsedTime ) { + if( mThreadMode == ThreadMode::RUN_IF_REQUESTED ) + { + extraFramesDropped = 0; + while( timeSinceLastFrame >= mDefaultFrameDurationNanoseconds ) + { + timeSinceLastFrame -= mDefaultFrameDurationNanoseconds; + extraFramesDropped++; + } + } + // If using the elapsed time, then calculate frameDelta as a multiple of mDefaultFrameDelta noOfFramesSinceLastUpdate += extraFramesDropped; @@ -625,6 +678,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() } // Check resize + bool surfaceResized = false; bool shouldSurfaceBeResized = ShouldSurfaceBeResized(); if( DALI_UNLIKELY( shouldSurfaceBeResized ) ) { @@ -632,6 +686,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() { LOG_UPDATE_RENDER_TRACE_FMT( "Resizing Surface" ); SurfaceResized(); + surfaceResized = true; } } @@ -671,18 +726,69 @@ void CombinedUpdateRenderController::UpdateRenderThread() Integration::RenderStatus renderStatus; AddPerformanceMarker( PerformanceInterface::RENDER_START ); - mCore.Render( renderStatus, mForceClear, mUploadWithoutRendering ); + + // Upload shared resources + mCore.PreRender( renderStatus, mForceClear, mUploadWithoutRendering ); + + if ( !mUploadWithoutRendering ) + { + // Go through each window + WindowContainer windows; + mAdaptorInterfaces.GetWindowContainerInterface( windows ); + + for( auto&& window : windows ) + { + Dali::Integration::Scene scene = window->GetScene(); + Dali::RenderSurfaceInterface* windowSurface = window->GetSurface(); + + if ( scene && windowSurface ) + { + Integration::RenderStatus windowRenderStatus; + + windowSurface->InitializeGraphics(); + + // clear previous frame damaged render items rects, buffer history is tracked on surface level + mDamagedRects.clear(); + + // Collect damage rects + mCore.PreRender( scene, mDamagedRects ); + + // Render off-screen frame buffers first if any + mCore.RenderScene( windowRenderStatus, scene, true ); + + Rect clippingRect; // Empty for fbo rendering + + // Switch to the EGL context of the surface, merge damaged areas for previous frames + windowSurface->PreRender( surfaceResized, mDamagedRects, clippingRect ); // Switch GL context + + if (clippingRect.IsEmpty()) + { + mDamagedRects.clear(); + } + + // Render the surface + mCore.RenderScene( windowRenderStatus, scene, false, clippingRect ); + + if( windowRenderStatus.NeedsPostRender() ) + { + windowSurface->PostRender( false, false, surfaceResized, mDamagedRects ); // Swap Buffer with damage + } + } + } + } + + mCore.PostRender( mUploadWithoutRendering ); ////////////////////////////// // DELETE SURFACE ////////////////////////////// - Integration::RenderSurface* deletedSurface = ShouldSurfaceBeDeleted(); + Dali::RenderSurfaceInterface* deletedSurface = ShouldSurfaceBeDeleted(); if( DALI_UNLIKELY( deletedSurface ) ) { LOG_UPDATE_RENDER_TRACE_FMT( "Deleting Surface" ); - mCore.SurfaceDeleted( deletedSurface ); + deletedSurface->DestroySurface(); SurfaceDeleted(); } @@ -747,15 +853,22 @@ void CombinedUpdateRenderController::UpdateRenderThread() } } - // Inform core of context destruction & shutdown EGL + // Inform core of context destruction mCore.ContextDestroyed(); - currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); - if( currentSurface ) + + WindowContainer windows; + mAdaptorInterfaces.GetWindowContainerInterface( windows ); + + // Destroy surfaces + for( auto&& window : windows ) { - currentSurface->DestroySurface(); - currentSurface = nullptr; + Dali::RenderSurfaceInterface* surface = window->GetSurface(); + surface->DestroySurface(); } + // Shutdown EGL + eglInterface->TerminateGles(); + LOG_UPDATE_RENDER( "THREAD DESTROYED" ); // Uninstall the logging function @@ -816,11 +929,11 @@ bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bo return ! mDestroyUpdateRenderThread; } -Integration::RenderSurface* CombinedUpdateRenderController::ShouldSurfaceBeReplaced() +Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeReplaced() { ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); - Integration::RenderSurface* newSurface = mNewSurface; + Dali::RenderSurfaceInterface* newSurface = mNewSurface; mNewSurface = NULL; return newSurface; @@ -829,14 +942,14 @@ Integration::RenderSurface* CombinedUpdateRenderController::ShouldSurfaceBeRepla void CombinedUpdateRenderController::SurfaceReplaced() { // Just increment the semaphore - sem_post( &mEventThreadSemaphore ); + sem_post( &mSurfaceSemaphore ); } -Integration::RenderSurface* CombinedUpdateRenderController::ShouldSurfaceBeDeleted() +Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeDeleted() { ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); - Integration::RenderSurface* deletedSurface = mDeletedSurface; + Dali::RenderSurfaceInterface* deletedSurface = mDeletedSurface; mDeletedSurface = NULL; return deletedSurface; @@ -845,7 +958,7 @@ Integration::RenderSurface* CombinedUpdateRenderController::ShouldSurfaceBeDelet void CombinedUpdateRenderController::SurfaceDeleted() { // Just increment the semaphore - sem_post( &mEventThreadSemaphore ); + sem_post( &mSurfaceSemaphore ); } bool CombinedUpdateRenderController::ShouldSurfaceBeResized()