X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fadaptor%2Fcommon%2Fcombined-update-render-controller.cpp;h=356cec057b2758d944da9f412fd5e87d0e877a61;hb=00e9dcda4086bddd3016e6d13d1d9f7823825ceb;hp=3291c4b5ef13e10658568f659ee10503c3c90614;hpb=ab707e9ca7437d4aa06353e97ee716c25e512495;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 3291c4b..356cec0 100644 --- a/dali/internal/adaptor/common/combined-update-render-controller.cpp +++ b/dali/internal/adaptor/common/combined-update-render-controller.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -19,51 +19,48 @@ #include // EXTERNAL INCLUDES -#include #include +#include #include +#include "dali/public-api/common/dali-common.h" // INTERNAL INCLUDES -#include #include +#include #include #include +#include #include #include -#include #include #include #include namespace Dali { - namespace Internal { - namespace Adaptor { - namespace { - const unsigned int CREATED_THREAD_COUNT = 1u; const int CONTINUOUS = -1; -const int ONCE = 1; +const int ONCE = 1; -const unsigned int TRUE = 1u; +const unsigned int TRUE = 1u; const unsigned int FALSE = 0u; -const unsigned int MILLISECONDS_PER_SECOND( 1e+3 ); -const float NANOSECONDS_TO_SECOND( 1e-9f ); -const unsigned int NANOSECONDS_PER_SECOND( 1e+9 ); -const unsigned int NANOSECONDS_PER_MILLISECOND( 1e+6 ); +const unsigned int MILLISECONDS_PER_SECOND(1e+3); +const float NANOSECONDS_TO_SECOND(1e-9f); +const unsigned int NANOSECONDS_PER_SECOND(1e+9); +const unsigned int NANOSECONDS_PER_MILLISECOND(1e+6); // The following values will get calculated at compile time -const float DEFAULT_FRAME_DURATION_IN_SECONDS( 1.0f / 60.0f ); -const uint64_t DEFAULT_FRAME_DURATION_IN_MILLISECONDS( DEFAULT_FRAME_DURATION_IN_SECONDS * MILLISECONDS_PER_SECOND ); -const uint64_t DEFAULT_FRAME_DURATION_IN_NANOSECONDS( DEFAULT_FRAME_DURATION_IN_SECONDS * NANOSECONDS_PER_SECOND ); +const float DEFAULT_FRAME_DURATION_IN_SECONDS(1.0f / 60.0f); +const uint64_t DEFAULT_FRAME_DURATION_IN_MILLISECONDS(DEFAULT_FRAME_DURATION_IN_SECONDS* MILLISECONDS_PER_SECOND); +const uint64_t DEFAULT_FRAME_DURATION_IN_NANOSECONDS(DEFAULT_FRAME_DURATION_IN_SECONDS* NANOSECONDS_PER_SECOND); /** * Handles the use case when an update-request is received JUST before we process a sleep-request. If we did not have an update-request count then @@ -89,56 +86,53 @@ const unsigned int MAXIMUM_UPDATE_REQUESTS = 2; // EVENT THREAD /////////////////////////////////////////////////////////////////////////////////////////////////// -CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions ) -: mFpsTracker( environmentOptions ), - mUpdateStatusLogger( environmentOptions ), - mEventThreadSemaphore(), - mGraphicsInitializeSemaphore(), +CombinedUpdateRenderController::CombinedUpdateRenderController(AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions, ThreadMode threadMode) +: mFpsTracker(environmentOptions), + mUpdateStatusLogger(environmentOptions), + mEventThreadSemaphore(0), + mSurfaceSemaphore(0), mUpdateRenderThreadWaitCondition(), - mAdaptorInterfaces( adaptorInterfaces ), - mPerformanceInterface( adaptorInterfaces.GetPerformanceInterface() ), - mCore( adaptorInterfaces.GetCore() ), - mEnvironmentOptions( environmentOptions ), - mNotificationTrigger( adaptorInterfaces.GetProcessCoreEventsTrigger() ), - mSleepTrigger( NULL ), - mPreRenderCallback( NULL ), - mUpdateRenderThread( NULL ), - mDefaultFrameDelta( 0.0f ), - mDefaultFrameDurationMilliseconds( 0u ), - mDefaultFrameDurationNanoseconds( 0u ), - mDefaultHalfFrameNanoseconds( 0u ), - mUpdateRequestCount( 0u ), - mRunning( FALSE ), - mUpdateRenderRunCount( 0 ), - mDestroyUpdateRenderThread( FALSE ), - mUpdateRenderThreadCanSleep( FALSE ), - mPendingRequestUpdate( FALSE ), - mUseElapsedTimeAfterWait( FALSE ), - mNewSurface( NULL ), - mDeletedSurface( nullptr ), - mPostRendering( FALSE ), - mSurfaceResized( FALSE ), - mForceClear( FALSE ), - mUploadWithoutRendering( FALSE ), - mFirstFrameAfterResume( FALSE ) + mAdaptorInterfaces(adaptorInterfaces), + mPerformanceInterface(adaptorInterfaces.GetPerformanceInterface()), + mCore(adaptorInterfaces.GetCore()), + mEnvironmentOptions(environmentOptions), + mNotificationTrigger(adaptorInterfaces.GetProcessCoreEventsTrigger()), + mSleepTrigger(NULL), + mPreRenderCallback(NULL), + mUpdateRenderThread(NULL), + mDefaultFrameDelta(0.0f), + mDefaultFrameDurationMilliseconds(0u), + mDefaultFrameDurationNanoseconds(0u), + mDefaultHalfFrameNanoseconds(0u), + mUpdateRequestCount(0u), + mRunning(FALSE), + mThreadMode(threadMode), + mUpdateRenderRunCount(0), + mDestroyUpdateRenderThread(FALSE), + mUpdateRenderThreadCanSleep(FALSE), + mPendingRequestUpdate(FALSE), + mUseElapsedTimeAfterWait(FALSE), + mNewSurface(NULL), + mDeletedSurface(nullptr), + mPostRendering(FALSE), + mSurfaceResized(0), + mForceClear(FALSE), + mUploadWithoutRendering(FALSE), + mFirstFrameAfterResume(FALSE) { LOG_EVENT_TRACE; // Initialise frame delta/duration variables first - SetRenderRefreshRate( environmentOptions.GetRenderRefreshRate() ); + SetRenderRefreshRate(environmentOptions.GetRenderRefreshRate()); // Set the thread-synchronization interface on the render-surface Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); - if( currentSurface ) + if(currentSurface) { - currentSurface->SetThreadSynchronization( *this ); + currentSurface->SetThreadSynchronization(*this); } - 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 ); + mSleepTrigger = TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &CombinedUpdateRenderController::ProcessSleepRequest), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER); } CombinedUpdateRenderController::~CombinedUpdateRenderController() @@ -156,12 +150,13 @@ void CombinedUpdateRenderController::Initialize() LOG_EVENT_TRACE; // Ensure Update/Render Thread not already created - DALI_ASSERT_ALWAYS( ! mUpdateRenderThread ); + DALI_ASSERT_ALWAYS(!mUpdateRenderThread); // Create Update/Render Thread + ConditionalWait::ScopedLock lock(mGraphicsInitializeWait); mUpdateRenderThread = new pthread_t(); - int error = pthread_create( mUpdateRenderThread, NULL, InternalUpdateRenderThreadEntryFunc, this ); - DALI_ASSERT_ALWAYS( !error && "Return code from pthread_create() when creating UpdateRenderThread" ); + int error = pthread_create(mUpdateRenderThread, NULL, InternalUpdateRenderThreadEntryFunc, this); + DALI_ASSERT_ALWAYS(!error && "Return code from pthread_create() when creating UpdateRenderThread"); // The Update/Render thread will now run and initialise the graphics interface etc. and will then wait for Start to be called // When this function returns, the application initialisation on the event thread should occur @@ -171,27 +166,27 @@ void CombinedUpdateRenderController::Start() { LOG_EVENT_TRACE; - DALI_ASSERT_ALWAYS( !mRunning && mUpdateRenderThread ); + DALI_ASSERT_ALWAYS(!mRunning && mUpdateRenderThread); // Wait until all threads created in Initialise are up and running - for( unsigned int i = 0; i < CREATED_THREAD_COUNT; ++i ) + for(unsigned int i = 0; i < CREATED_THREAD_COUNT; ++i) { - sem_wait( &mEventThreadSemaphore ); + mEventThreadSemaphore.Acquire(); } + mRunning = TRUE; + + LOG_EVENT("Startup Complete, starting Update/Render Thread"); + + RunUpdateRenderThread(CONTINUOUS, AnimationProgression::NONE, UpdateMode::NORMAL); + Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); - if( currentSurface ) + if(currentSurface) { currentSurface->StartRender(); } - mRunning = TRUE; - - LOG_EVENT( "Startup Complete, starting Update/Render Thread" ); - - RunUpdateRenderThread( CONTINUOUS, AnimationProgression::NONE, UpdateMode::NORMAL ); - - DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Start\n" ); + DALI_LOG_RELEASE_INFO("CombinedUpdateRenderController::Start\n"); } void CombinedUpdateRenderController::Pause() @@ -202,32 +197,32 @@ void CombinedUpdateRenderController::Pause() PauseUpdateRenderThread(); - AddPerformanceMarker( PerformanceInterface::PAUSED ); + AddPerformanceMarker(PerformanceInterface::PAUSED); - DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Pause\n" ); + DALI_LOG_RELEASE_INFO("CombinedUpdateRenderController::Pause\n"); } void CombinedUpdateRenderController::Resume() { LOG_EVENT_TRACE; - if( !mRunning && IsUpdateRenderThreadPaused() ) + if(!mRunning && IsUpdateRenderThreadPaused()) { - LOG_EVENT( "Resuming" ); + LOG_EVENT("Resuming"); - RunUpdateRenderThread( CONTINUOUS, AnimationProgression::USE_ELAPSED_TIME, UpdateMode::NORMAL ); + RunUpdateRenderThread(CONTINUOUS, AnimationProgression::USE_ELAPSED_TIME, UpdateMode::NORMAL); - AddPerformanceMarker( PerformanceInterface::RESUME ); + AddPerformanceMarker(PerformanceInterface::RESUME); - mRunning = TRUE; - mForceClear = TRUE; + mRunning = TRUE; + mForceClear = TRUE; mFirstFrameAfterResume = TRUE; - DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Resume\n" ); + DALI_LOG_RELEASE_INFO("CombinedUpdateRenderController::Resume\n"); } else { - DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Resume: Already resumed [%d, %d, %d]\n", mRunning, mUpdateRenderRunCount, mUpdateRenderThreadCanSleep ); + DALI_LOG_RELEASE_INFO("CombinedUpdateRenderController::Resume: Already resumed [%d, %d, %d]\n", mRunning, mUpdateRenderRunCount, mUpdateRenderThreadCanSleep); } } @@ -237,19 +232,19 @@ void CombinedUpdateRenderController::Stop() // Stop Rendering and the Update/Render Thread Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); - if( currentSurface ) + if(currentSurface) { currentSurface->StopRender(); } StopUpdateRenderThread(); - if( mUpdateRenderThread ) + if(mUpdateRenderThread) { - LOG_EVENT( "Destroying UpdateRenderThread" ); + LOG_EVENT("Destroying UpdateRenderThread"); // wait for the thread to finish - pthread_join( *mUpdateRenderThread, NULL ); + pthread_join(*mUpdateRenderThread, NULL); delete mUpdateRenderThread; mUpdateRenderThread = NULL; @@ -257,7 +252,7 @@ void CombinedUpdateRenderController::Stop() mRunning = FALSE; - DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Stop\n" ); + DALI_LOG_RELEASE_INFO("CombinedUpdateRenderController::Stop\n"); } void CombinedUpdateRenderController::RequestUpdate() @@ -265,100 +260,101 @@ void CombinedUpdateRenderController::RequestUpdate() LOG_EVENT_TRACE; // Increment the update-request count to the maximum - if( mUpdateRequestCount < MAXIMUM_UPDATE_REQUESTS ) + if(mUpdateRequestCount < MAXIMUM_UPDATE_REQUESTS) { ++mUpdateRequestCount; } - if( mRunning && IsUpdateRenderThreadPaused() ) + if(mRunning && IsUpdateRenderThreadPaused()) { - LOG_EVENT( "Processing" ); + LOG_EVENT("Processing"); - RunUpdateRenderThread( CONTINUOUS, AnimationProgression::NONE, UpdateMode::NORMAL ); + RunUpdateRenderThread(CONTINUOUS, AnimationProgression::NONE, UpdateMode::NORMAL); } - ConditionalWait::ScopedLock updateLock( mUpdateRenderThreadWaitCondition ); + ConditionalWait::ScopedLock updateLock(mUpdateRenderThreadWaitCondition); mPendingRequestUpdate = TRUE; } -void CombinedUpdateRenderController::RequestUpdateOnce( UpdateMode updateMode ) +void CombinedUpdateRenderController::RequestUpdateOnce(UpdateMode updateMode) { // Increment the update-request count to the maximum - if( mUpdateRequestCount < MAXIMUM_UPDATE_REQUESTS ) + if(mUpdateRequestCount < MAXIMUM_UPDATE_REQUESTS) { ++mUpdateRequestCount; } - if( IsUpdateRenderThreadPaused() ) + if(IsUpdateRenderThreadPaused() || updateMode == UpdateMode::FORCE_RENDER) { LOG_EVENT_TRACE; // Run Update/Render once - RunUpdateRenderThread( ONCE, AnimationProgression::NONE, updateMode ); + RunUpdateRenderThread(ONCE, AnimationProgression::NONE, updateMode); } } -void CombinedUpdateRenderController::ReplaceSurface( Dali::RenderSurfaceInterface* newSurface ) +void CombinedUpdateRenderController::ReplaceSurface(Dali::RenderSurfaceInterface* newSurface) { LOG_EVENT_TRACE; - if( mUpdateRenderThread ) + if(mUpdateRenderThread) { // Set the ThreadSyncronizationInterface on the new surface - newSurface->SetThreadSynchronization( *this ); + newSurface->SetThreadSynchronization(*this); - LOG_EVENT( "Starting to replace the surface, event-thread blocked" ); + LOG_EVENT("Starting to replace the surface, event-thread blocked"); // Start replacing the surface. { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); mPostRendering = FALSE; // Clear the post-rendering flag as Update/Render thread will replace the surface now - mNewSurface = newSurface; - mUpdateRenderThreadWaitCondition.Notify( lock ); + mNewSurface = newSurface; + mUpdateRenderThreadWaitCondition.Notify(lock); } // Wait until the surface has been replaced - sem_wait( &mEventThreadSemaphore ); + mSurfaceSemaphore.Acquire(); - LOG_EVENT( "Surface replaced, event-thread continuing" ); + LOG_EVENT("Surface replaced, event-thread continuing"); } } -void CombinedUpdateRenderController::DeleteSurface( Dali::RenderSurfaceInterface* surface ) +void CombinedUpdateRenderController::DeleteSurface(Dali::RenderSurfaceInterface* surface) { LOG_EVENT_TRACE; - if( mUpdateRenderThread ) + if(mUpdateRenderThread) { - LOG_EVENT( "Starting to delete the surface, event-thread blocked" ); + LOG_EVENT("Starting to delete the surface, event-thread blocked"); // Start replacing the surface. { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); - mPostRendering = FALSE; // Clear the post-rendering flag as Update/Render thread will delete the surface now + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); + mPostRendering = FALSE; // Clear the post-rendering flag as Update/Render thread will delete the surface now mDeletedSurface = surface; - mUpdateRenderThreadWaitCondition.Notify( lock ); + mUpdateRenderThreadWaitCondition.Notify(lock); } // Wait until the surface has been deleted - sem_wait( &mEventThreadSemaphore ); + mSurfaceSemaphore.Acquire(); - LOG_EVENT( "Surface deleted, event-thread continuing" ); + LOG_EVENT("Surface deleted, event-thread continuing"); } } void CombinedUpdateRenderController::WaitForGraphicsInitialization() { + ConditionalWait::ScopedLock lk(mGraphicsInitializeWait); LOG_EVENT_TRACE; - if( mUpdateRenderThread ) + if(mUpdateRenderThread) { - LOG_EVENT( "Waiting for graphics initialisation, event-thread blocked" ); + LOG_EVENT("Waiting for graphics initialisation, event-thread blocked"); // Wait until the graphics has been initialised - sem_wait( &mGraphicsInitializeSemaphore ); + mGraphicsInitializeWait.Wait(lk); - LOG_EVENT( "graphics initialised, event-thread continuing" ); + LOG_EVENT("graphics initialised, event-thread continuing"); } } @@ -366,48 +362,49 @@ void CombinedUpdateRenderController::ResizeSurface() { LOG_EVENT_TRACE; - LOG_EVENT( "Resize the surface" ); + LOG_EVENT("Resize the surface"); { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); mPostRendering = FALSE; // Clear the post-rendering flag as Update/Render thread will resize the surface now - mSurfaceResized = TRUE; - mUpdateRenderThreadWaitCondition.Notify( lock ); + // Surface is resized and the surface resized count is increased. + mSurfaceResized++; + mUpdateRenderThreadWaitCondition.Notify(lock); } } -void CombinedUpdateRenderController::SetRenderRefreshRate( unsigned int numberOfFramesPerRender ) +void CombinedUpdateRenderController::SetRenderRefreshRate(unsigned int numberOfFramesPerRender) { // Not protected by lock, but written to rarely so not worth adding a lock when reading - mDefaultFrameDelta = numberOfFramesPerRender * DEFAULT_FRAME_DURATION_IN_SECONDS; - mDefaultFrameDurationMilliseconds = uint64_t( numberOfFramesPerRender ) * DEFAULT_FRAME_DURATION_IN_MILLISECONDS; - mDefaultFrameDurationNanoseconds = uint64_t( numberOfFramesPerRender ) * DEFAULT_FRAME_DURATION_IN_NANOSECONDS; - mDefaultHalfFrameNanoseconds = mDefaultFrameDurationNanoseconds / 2u; + mDefaultFrameDelta = numberOfFramesPerRender * DEFAULT_FRAME_DURATION_IN_SECONDS; + mDefaultFrameDurationMilliseconds = uint64_t(numberOfFramesPerRender) * DEFAULT_FRAME_DURATION_IN_MILLISECONDS; + mDefaultFrameDurationNanoseconds = uint64_t(numberOfFramesPerRender) * DEFAULT_FRAME_DURATION_IN_NANOSECONDS; + mDefaultHalfFrameNanoseconds = mDefaultFrameDurationNanoseconds / 2u; - LOG_EVENT( "mDefaultFrameDelta(%.6f), mDefaultFrameDurationMilliseconds(%lld), mDefaultFrameDurationNanoseconds(%lld)", mDefaultFrameDelta, mDefaultFrameDurationMilliseconds, mDefaultFrameDurationNanoseconds ); + LOG_EVENT("mDefaultFrameDelta(%.6f), mDefaultFrameDurationMilliseconds(%lld), mDefaultFrameDurationNanoseconds(%lld)", mDefaultFrameDelta, mDefaultFrameDurationMilliseconds, mDefaultFrameDurationNanoseconds); } -void CombinedUpdateRenderController::SetPreRenderCallback( CallbackBase* callback ) +void CombinedUpdateRenderController::SetPreRenderCallback(CallbackBase* callback) { LOG_EVENT_TRACE; - LOG_EVENT( "Set PreRender Callback" ); + LOG_EVENT("Set PreRender Callback"); - ConditionalWait::ScopedLock updateLock( mUpdateRenderThreadWaitCondition ); - if( mPreRenderCallback ) + ConditionalWait::ScopedLock updateLock(mUpdateRenderThreadWaitCondition); + if(mPreRenderCallback) { delete mPreRenderCallback; } mPreRenderCallback = callback; } -void CombinedUpdateRenderController::AddSurface( Dali::RenderSurfaceInterface* surface ) +void CombinedUpdateRenderController::AddSurface(Dali::RenderSurfaceInterface* surface) { LOG_EVENT_TRACE; - LOG_EVENT( "Surface is added" ); - if( mUpdateRenderThread ) + LOG_EVENT("Surface is added"); + if(mUpdateRenderThread) { // Set the ThreadSyncronizationInterface on the added surface - surface->SetThreadSynchronization( *this ); + surface->SetThreadSynchronization(*this); } } @@ -415,35 +412,63 @@ void CombinedUpdateRenderController::AddSurface( Dali::RenderSurfaceInterface* s // EVENT THREAD /////////////////////////////////////////////////////////////////////////////////////////////////// -void CombinedUpdateRenderController::RunUpdateRenderThread( int numberOfCycles, AnimationProgression animationProgression, UpdateMode updateMode ) +void CombinedUpdateRenderController::RunUpdateRenderThread(int numberOfCycles, AnimationProgression animationProgression, UpdateMode updateMode) { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); - mUpdateRenderRunCount = numberOfCycles; + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); + + 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 ); + mUploadWithoutRendering = (updateMode == UpdateMode::SKIP_RENDER); + LOG_COUNTER_EVENT("mUpdateRenderRunCount: %d, mUseElapsedTimeAfterWait: %d", mUpdateRenderRunCount, mUseElapsedTimeAfterWait); + mUpdateRenderThreadWaitCondition.Notify(lock); } void CombinedUpdateRenderController::PauseUpdateRenderThread() { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); mUpdateRenderRunCount = 0; } void CombinedUpdateRenderController::StopUpdateRenderThread() { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); mDestroyUpdateRenderThread = TRUE; - mUpdateRenderThreadWaitCondition.Notify( lock ); + mUpdateRenderThreadWaitCondition.Notify(lock); } bool CombinedUpdateRenderController::IsUpdateRenderThreadPaused() { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); - return ( mUpdateRenderRunCount != CONTINUOUS ) || // Report paused if NOT continuously running - mUpdateRenderThreadCanSleep; // Report paused if sleeping + 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 } void CombinedUpdateRenderController::ProcessSleepRequest() @@ -451,18 +476,18 @@ void CombinedUpdateRenderController::ProcessSleepRequest() LOG_EVENT_TRACE; // Decrement Update request count - if( mUpdateRequestCount > 0 ) + if(mUpdateRequestCount > 0) { --mUpdateRequestCount; } // Can sleep if our update-request count is 0 // Update/Render thread can choose to carry on updating if it determines more update/renders are required - if( mUpdateRequestCount == 0 ) + if(mUpdateRequestCount == 0) { - LOG_EVENT( "Going to sleep" ); + LOG_EVENT("Going to sleep"); - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); mUpdateRenderThreadCanSleep = TRUE; } } @@ -481,56 +506,19 @@ void CombinedUpdateRenderController::UpdateRenderThread() // Install a function for tracing mEnvironmentOptions.InstallTraceFunction(); - LOG_UPDATE_RENDER( "THREAD CREATED" ); - - // Initialize EGL & OpenGL - Dali::DisplayConnection& displayConnection = mAdaptorInterfaces.GetDisplayConnectionInterface(); - displayConnection.Initialize(); - - // EGL has been initialised at this point - NotifyGraphicsInitialised(); - - RenderSurfaceInterface* currentSurface = nullptr; + LOG_UPDATE_RENDER("THREAD CREATED"); + // Initialize graphics GraphicsInterface& graphics = mAdaptorInterfaces.GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - - // This will only be created once - EglInterface* eglInterface = &eglGraphics->GetEglInterface(); - - Internal::Adaptor::EglImplementation& eglImpl = static_cast( *eglInterface ); + graphics.Initialize(); - // Try to use OpenGL es 3.0 - // ChooseConfig returns false here when the device only support gles 2.0. - // Because eglChooseConfig with gles 3.0 setting fails when the device only support gles 2.0 and Our default setting is gles 3.0. - if( !eglImpl.ChooseConfig( true, COLOR_DEPTH_32 ) ) - { - // Retry to use OpenGL es 2.0 - eglGraphics->SetGlesVersion( 20 ); - eglImpl.ChooseConfig( true, COLOR_DEPTH_32 ); - } - - // Check whether surfaceless context is supported - bool isSurfacelessContextSupported = eglImpl.IsSurfacelessContextSupported(); - eglGraphics->SetIsSurfacelessContextSupported( isSurfacelessContextSupported ); + Dali::DisplayConnection& displayConnection = mAdaptorInterfaces.GetDisplayConnectionInterface(); + displayConnection.Initialize(); //@todo Move InitializeGraphics code into graphics implementation - if ( isSurfacelessContextSupported ) - { - // Create a surfaceless OpenGL context for shared resources - eglImpl.CreateContext(); - eglImpl.MakeContextCurrent( EGL_NO_SURFACE, eglImpl.GetContext() ); - } - else - { - currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); - if( currentSurface ) - { - currentSurface->InitializeGraphics(); - currentSurface->MakeContextCurrent(); - } - } + NotifyGraphicsInitialised(); - eglGraphics->GetGlesInterface().ContextCreated(); + //@todo Vk swaps this around, but we need to support surfaceless context for multi-window + graphics.ConfigureSurface(mAdaptorInterfaces.GetRenderSurfaceInterface()); // Tell core it has a context mCore.ContextCreated(); @@ -539,36 +527,36 @@ void CombinedUpdateRenderController::UpdateRenderThread() // Update time uint64_t lastFrameTime; - TimeService::GetNanoseconds( lastFrameTime ); + TimeService::GetNanoseconds(lastFrameTime); - LOG_UPDATE_RENDER( "THREAD INITIALISED" ); + LOG_UPDATE_RENDER("THREAD INITIALISED"); - bool useElapsedTime = true; - bool updateRequired = true; - uint64_t timeToSleepUntil = 0; - int extraFramesDropped = 0; + bool useElapsedTime = true; + bool updateRequired = true; + uint64_t timeToSleepUntil = 0; + int extraFramesDropped = 0; const unsigned int renderToFboInterval = mEnvironmentOptions.GetRenderToFboInterval(); - const bool renderToFboEnabled = 0u != renderToFboInterval; - unsigned int frameCount = 0u; + const bool renderToFboEnabled = 0u != renderToFboInterval; + unsigned int frameCount = 0u; - while( UpdateRenderReady( useElapsedTime, updateRequired, timeToSleepUntil ) ) + while(UpdateRenderReady(useElapsedTime, updateRequired, timeToSleepUntil)) { LOG_UPDATE_RENDER_TRACE; // Performance statistics are logged upon a VSYNC tick so use this point for a VSync marker - AddPerformanceMarker( PerformanceInterface::VSYNC ); + AddPerformanceMarker(PerformanceInterface::VSYNC); uint64_t currentFrameStartTime = 0; - TimeService::GetNanoseconds( currentFrameStartTime ); + TimeService::GetNanoseconds(currentFrameStartTime); - const uint64_t timeSinceLastFrame = currentFrameStartTime - lastFrameTime; + uint64_t timeSinceLastFrame = currentFrameStartTime - lastFrameTime; // Optional FPS Tracking when continuously rendering - if( useElapsedTime && mFpsTracker.Enabled() ) + if(useElapsedTime && mFpsTracker.Enabled()) { float absoluteTimeSinceLastRender = timeSinceLastFrame * NANOSECONDS_TO_SECOND; - mFpsTracker.Track( absoluteTimeSinceLastRender ); + mFpsTracker.Track(absoluteTimeSinceLastRender); } lastFrameTime = currentFrameStartTime; // Store frame start time @@ -578,16 +566,15 @@ void CombinedUpdateRenderController::UpdateRenderThread() ////////////////////////////// Dali::RenderSurfaceInterface* newSurface = ShouldSurfaceBeReplaced(); - if( DALI_UNLIKELY( newSurface ) ) + if(DALI_UNLIKELY(newSurface)) { - LOG_UPDATE_RENDER_TRACE_FMT( "Replacing Surface" ); + LOG_UPDATE_RENDER_TRACE_FMT("Replacing Surface"); // This is designed for replacing pixmap surfaces, but should work for window as well // we need to delete the surface and renderable (pixmap / window) // Then create a new pixmap/window and new surface // If the new surface has a different display connection, then the context will be lost mAdaptorInterfaces.GetDisplayConnectionInterface().Initialize(); - newSurface->InitializeGraphics(); - newSurface->MakeContextCurrent(); + graphics.ActivateSurfaceContext(newSurface); // TODO: ReplaceGraphicsSurface doesn't work, InitializeGraphics() // already creates new surface window, the surface and the context. // We probably don't need ReplaceGraphicsSurface at all. @@ -595,62 +582,59 @@ void CombinedUpdateRenderController::UpdateRenderThread() SurfaceReplaced(); } - const bool isRenderingToFbo = renderToFboEnabled && ( ( 0u == frameCount ) || ( 0u != frameCount % renderToFboInterval ) ); + const bool isRenderingToFbo = renderToFboEnabled && ((0u == frameCount) || (0u != frameCount % renderToFboInterval)); ++frameCount; ////////////////////////////// // UPDATE ////////////////////////////// - const unsigned int currentTime = currentFrameStartTime / NANOSECONDS_PER_MILLISECOND; + const unsigned int currentTime = currentFrameStartTime / NANOSECONDS_PER_MILLISECOND; const unsigned int nextFrameTime = currentTime + mDefaultFrameDurationMilliseconds; uint64_t noOfFramesSinceLastUpdate = 1; - float frameDelta = 0.0f; - if( useElapsedTime ) + 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; frameDelta = mDefaultFrameDelta * noOfFramesSinceLastUpdate; } - LOG_UPDATE_RENDER( "timeSinceLastFrame(%llu) noOfFramesSinceLastUpdate(%u) frameDelta(%.6f)", timeSinceLastFrame, noOfFramesSinceLastUpdate, frameDelta ); + LOG_UPDATE_RENDER("timeSinceLastFrame(%llu) noOfFramesSinceLastUpdate(%u) frameDelta(%.6f)", timeSinceLastFrame, noOfFramesSinceLastUpdate, frameDelta); Integration::UpdateStatus updateStatus; - AddPerformanceMarker( PerformanceInterface::UPDATE_START ); - mCore.Update( frameDelta, - currentTime, - nextFrameTime, - updateStatus, - renderToFboEnabled, - isRenderingToFbo ); - AddPerformanceMarker( PerformanceInterface::UPDATE_END ); + AddPerformanceMarker(PerformanceInterface::UPDATE_START); + mCore.Update(frameDelta, + currentTime, + nextFrameTime, + updateStatus, + renderToFboEnabled, + isRenderingToFbo); + AddPerformanceMarker(PerformanceInterface::UPDATE_END); unsigned int keepUpdatingStatus = updateStatus.KeepUpdating(); // Tell the event-thread to wake up (if asleep) and send a notification event to Core if required - if( updateStatus.NeedsNotification() ) + if(updateStatus.NeedsNotification()) { mNotificationTrigger.Trigger(); - LOG_UPDATE_RENDER( "Notification Triggered" ); - } - - // Check resize - bool surfaceResized = false; - bool shouldSurfaceBeResized = ShouldSurfaceBeResized(); - if( DALI_UNLIKELY( shouldSurfaceBeResized ) ) - { - if( updateStatus.SurfaceRectChanged() ) - { - LOG_UPDATE_RENDER_TRACE_FMT( "Resizing Surface" ); - SurfaceResized(); - surfaceResized = true; - } + LOG_UPDATE_RENDER("Notification Triggered"); } // Optional logging of update/render status - mUpdateStatusLogger.Log( keepUpdatingStatus ); + mUpdateStatusLogger.Log(keepUpdatingStatus); ////////////////////////////// // RENDER @@ -658,95 +642,113 @@ void CombinedUpdateRenderController::UpdateRenderThread() mAdaptorInterfaces.GetDisplayConnectionInterface().ConsumeEvents(); - if( mPreRenderCallback != NULL ) + if(mPreRenderCallback != NULL) { bool keepCallback = CallbackBase::ExecuteReturn(*mPreRenderCallback); - if( ! keepCallback ) + if(!keepCallback) { delete mPreRenderCallback; mPreRenderCallback = NULL; } } - if( eglImpl.IsSurfacelessContextSupported() ) - { - // Make the shared surfaceless context as current before rendering - eglImpl.MakeContextCurrent( EGL_NO_SURFACE, eglImpl.GetContext() ); - } + graphics.ActivateResourceContext(); - if( mFirstFrameAfterResume ) + if(mFirstFrameAfterResume) { // mFirstFrameAfterResume is set to true when the thread is resumed - // Let eglImplementation know the first frame after thread initialized or resumed. - eglImpl.SetFirstFrameAfterResume(); + // Let graphics know the first frame after thread initialized or resumed. + graphics.SetFirstFrameAfterResume(); mFirstFrameAfterResume = FALSE; } Integration::RenderStatus renderStatus; - AddPerformanceMarker( PerformanceInterface::RENDER_START ); + AddPerformanceMarker(PerformanceInterface::RENDER_START); // Upload shared resources - mCore.PreRender( renderStatus, mForceClear, mUploadWithoutRendering ); + mCore.PreRender(renderStatus, mForceClear, mUploadWithoutRendering); - if ( !mUploadWithoutRendering ) + if(!mUploadWithoutRendering) { // Go through each window WindowContainer windows; - mAdaptorInterfaces.GetWindowContainerInterface( windows ); + mAdaptorInterfaces.GetWindowContainerInterface(windows); + + bool sceneSurfaceResized; - for( auto&& window : windows ) + for(auto&& window : windows) { - Dali::Integration::Scene scene = window->GetScene(); + Dali::Integration::Scene scene = window->GetScene(); Dali::RenderSurfaceInterface* windowSurface = window->GetSurface(); - if ( scene && windowSurface ) + if(scene && windowSurface) { - windowSurface->InitializeGraphics(); + Integration::RenderStatus windowRenderStatus; + + // Get Surface Resized flag + sceneSurfaceResized = scene.IsSurfaceRectChanged(); + windowSurface->SetIsResizing(sceneSurfaceResized); + + // 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( scene, true ); + mCore.RenderScene(windowRenderStatus, scene, true); - // Switch to the EGL context of the surface - windowSurface->PreRender( surfaceResized ); // Switch GL context + Rect clippingRect; // Empty for fbo rendering + + // Switch to the context of the surface, merge damaged areas for previous frames + windowSurface->PreRender(sceneSurfaceResized, mDamagedRects, clippingRect); // Switch GL context // Render the surface - mCore.RenderScene( scene, false ); + mCore.RenderScene(windowRenderStatus, scene, false, clippingRect); + + // Buffer swapping now happens when the surface render target is presented. - if( renderStatus.NeedsPostRender() ) + // If surface is resized, the surface resized count is decreased. + if(DALI_UNLIKELY(sceneSurfaceResized)) { - windowSurface->PostRender( false, false, surfaceResized ); // Swap Buffer + SurfaceResized(); } } } } - mCore.PostRender( mUploadWithoutRendering ); + if(!mUploadWithoutRendering) + { + graphics.PostRender(); + } + + mCore.PostRender(mUploadWithoutRendering); ////////////////////////////// // DELETE SURFACE ////////////////////////////// Dali::RenderSurfaceInterface* deletedSurface = ShouldSurfaceBeDeleted(); - if( DALI_UNLIKELY( deletedSurface ) ) + if(DALI_UNLIKELY(deletedSurface)) { - LOG_UPDATE_RENDER_TRACE_FMT( "Deleting Surface" ); + LOG_UPDATE_RENDER_TRACE_FMT("Deleting Surface"); deletedSurface->DestroySurface(); SurfaceDeleted(); } - AddPerformanceMarker( PerformanceInterface::RENDER_END ); + AddPerformanceMarker(PerformanceInterface::RENDER_END); mForceClear = false; // Trigger event thread to request Update/Render thread to sleep if update not required - if( ( Integration::KeepUpdating::NOT_REQUESTED == keepUpdatingStatus ) && !renderStatus.NeedsUpdate() ) + if((Integration::KeepUpdating::NOT_REQUESTED == keepUpdatingStatus) && !renderStatus.NeedsUpdate()) { mSleepTrigger->Trigger(); updateRequired = false; - LOG_UPDATE_RENDER( "Sleep Triggered" ); + LOG_UPDATE_RENDER("Sleep Triggered"); } else { @@ -759,7 +761,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() extraFramesDropped = 0; - if (timeToSleepUntil == 0) + if(timeToSleepUntil == 0) { // If this is the first frame after the thread is initialized or resumed, we // use the actual time the current frame starts from to calculate the time to @@ -778,103 +780,106 @@ void CombinedUpdateRenderController::UpdateRenderThread() // Check the current time at the end of the frame uint64_t currentFrameEndTime = 0; - TimeService::GetNanoseconds( currentFrameEndTime ); - while ( currentFrameEndTime > timeToSleepUntil + mDefaultFrameDurationNanoseconds ) + TimeService::GetNanoseconds(currentFrameEndTime); + while(currentFrameEndTime > timeToSleepUntil + mDefaultFrameDurationNanoseconds) { - // We are more than one frame behind already, so just drop the next frames - // until the sleep-until time is later than the current time so that we can - // catch up. - timeToSleepUntil += mDefaultFrameDurationNanoseconds; - extraFramesDropped++; + // We are more than one frame behind already, so just drop the next frames + // until the sleep-until time is later than the current time so that we can + // catch up. + timeToSleepUntil += mDefaultFrameDurationNanoseconds; + extraFramesDropped++; } } // Render to FBO is intended to measure fps above 60 so sleep is not wanted. - if( 0u == renderToFboInterval ) + if(0u == renderToFboInterval) { // Sleep until at least the the default frame duration has elapsed. This will return immediately if the specified end-time has already passed. - TimeService::SleepUntil( timeToSleepUntil ); + TimeService::SleepUntil(timeToSleepUntil); } } // 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(); + graphics.Shutdown(); - LOG_UPDATE_RENDER( "THREAD DESTROYED" ); + LOG_UPDATE_RENDER("THREAD DESTROYED"); // Uninstall the logging function mEnvironmentOptions.UnInstallLogFunction(); } -bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bool updateRequired, uint64_t& timeToSleepUntil ) +bool CombinedUpdateRenderController::UpdateRenderReady(bool& useElapsedTime, bool updateRequired, uint64_t& timeToSleepUntil) { useElapsedTime = true; - ConditionalWait::ScopedLock updateLock( mUpdateRenderThreadWaitCondition ); - while( ( ! mUpdateRenderRunCount || // Should try to wait if event-thread has paused the Update/Render thread - ( mUpdateRenderThreadCanSleep && ! updateRequired && ! mPendingRequestUpdate ) ) && // Ensure we wait if we're supposed to be sleeping AND do not require another update - ! mDestroyUpdateRenderThread && // Ensure we don't wait if the update-render-thread is supposed to be destroyed - ! mNewSurface && // Ensure we don't wait if we need to replace the surface - ! mDeletedSurface && // Ensure we don't wait if we need to delete the surface - ! mSurfaceResized ) // Ensure we don't wait if we need to resize the surface + ConditionalWait::ScopedLock updateLock(mUpdateRenderThreadWaitCondition); + while((!mUpdateRenderRunCount || // Should try to wait if event-thread has paused the Update/Render thread + (mUpdateRenderThreadCanSleep && !updateRequired && !mPendingRequestUpdate)) && // Ensure we wait if we're supposed to be sleeping AND do not require another update + !mDestroyUpdateRenderThread && // Ensure we don't wait if the update-render-thread is supposed to be destroyed + !mNewSurface && // Ensure we don't wait if we need to replace the surface + !mDeletedSurface && // Ensure we don't wait if we need to delete the surface + !mSurfaceResized) // Ensure we don't wait if we need to resize the surface { - LOG_UPDATE_RENDER( "WAIT: mUpdateRenderRunCount: %d", mUpdateRenderRunCount ); - LOG_UPDATE_RENDER( " mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate ); - LOG_UPDATE_RENDER( " mDestroyUpdateRenderThread: %d", mDestroyUpdateRenderThread ); - LOG_UPDATE_RENDER( " mNewSurface: %d", mNewSurface ); - LOG_UPDATE_RENDER( " mDeletedSurface: %d", mDeletedSurface ); - LOG_UPDATE_RENDER( " mSurfaceResized: %d", mSurfaceResized ); + LOG_UPDATE_RENDER("WAIT: mUpdateRenderRunCount: %d", mUpdateRenderRunCount); + LOG_UPDATE_RENDER(" mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate); + LOG_UPDATE_RENDER(" mDestroyUpdateRenderThread: %d", mDestroyUpdateRenderThread); + LOG_UPDATE_RENDER(" mNewSurface: %d", mNewSurface); + LOG_UPDATE_RENDER(" mDeletedSurface: %d", mDeletedSurface); + LOG_UPDATE_RENDER(" mSurfaceResized: %d", mSurfaceResized); // Reset the time when the thread is waiting, so the sleep-until time for // the first frame after resuming should be based on the actual start time // of the first frame. timeToSleepUntil = 0; - mUpdateRenderThreadWaitCondition.Wait( updateLock ); + mUpdateRenderThreadWaitCondition.Wait(updateLock); - if( ! mUseElapsedTimeAfterWait ) + if(!mUseElapsedTimeAfterWait) { useElapsedTime = false; } } - LOG_COUNTER_UPDATE_RENDER( "mUpdateRenderRunCount: %d", mUpdateRenderRunCount ); - LOG_COUNTER_UPDATE_RENDER( "mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate ); - LOG_COUNTER_UPDATE_RENDER( "mDestroyUpdateRenderThread: %d", mDestroyUpdateRenderThread ); - LOG_COUNTER_UPDATE_RENDER( "mNewSurface: %d", mNewSurface ); - LOG_COUNTER_UPDATE_RENDER( "mDeletedSurface: %d", mDeletedSurface ); - LOG_COUNTER_UPDATE_RENDER( "mSurfaceResized: %d", mSurfaceResized ); + LOG_COUNTER_UPDATE_RENDER("mUpdateRenderRunCount: %d", mUpdateRenderRunCount); + LOG_COUNTER_UPDATE_RENDER("mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate); + LOG_COUNTER_UPDATE_RENDER("mDestroyUpdateRenderThread: %d", mDestroyUpdateRenderThread); + LOG_COUNTER_UPDATE_RENDER("mNewSurface: %d", mNewSurface); + LOG_COUNTER_UPDATE_RENDER("mDeletedSurface: %d", mDeletedSurface); + LOG_COUNTER_UPDATE_RENDER("mSurfaceResized: %d", mSurfaceResized); - mUseElapsedTimeAfterWait = FALSE; + mUseElapsedTimeAfterWait = FALSE; mUpdateRenderThreadCanSleep = FALSE; - mPendingRequestUpdate = FALSE; + mPendingRequestUpdate = FALSE; // If we've been asked to run Update/Render cycles a finite number of times then decrement so we wait after the // requested number of cycles - if( mUpdateRenderRunCount > 0 ) + if(mUpdateRenderRunCount > 0) { --mUpdateRenderRunCount; } // Keep the update-render thread alive if this thread is NOT to be destroyed - return ! mDestroyUpdateRenderThread; + return !mDestroyUpdateRenderThread; } Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeReplaced() { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); Dali::RenderSurfaceInterface* newSurface = mNewSurface; - mNewSurface = NULL; + mNewSurface = NULL; return newSurface; } @@ -882,15 +887,15 @@ Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeRep void CombinedUpdateRenderController::SurfaceReplaced() { // Just increment the semaphore - sem_post( &mEventThreadSemaphore ); + mSurfaceSemaphore.Release(1); } Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeDeleted() { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); Dali::RenderSurfaceInterface* deletedSurface = mDeletedSurface; - mDeletedSurface = NULL; + mDeletedSurface = NULL; return deletedSurface; } @@ -898,19 +903,16 @@ Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeDel void CombinedUpdateRenderController::SurfaceDeleted() { // Just increment the semaphore - sem_post( &mEventThreadSemaphore ); -} - -bool CombinedUpdateRenderController::ShouldSurfaceBeResized() -{ - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); - return mSurfaceResized; + mSurfaceSemaphore.Release(1); } void CombinedUpdateRenderController::SurfaceResized() { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); - mSurfaceResized = FALSE; + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); + if(mSurfaceResized) + { + mSurfaceResized--; + } } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -920,19 +922,19 @@ void CombinedUpdateRenderController::SurfaceResized() void CombinedUpdateRenderController::NotifyThreadInitialised() { // Just increment the semaphore - sem_post( &mEventThreadSemaphore ); + mEventThreadSemaphore.Release(1); } void CombinedUpdateRenderController::NotifyGraphicsInitialised() { - sem_post( &mGraphicsInitializeSemaphore ); + mGraphicsInitializeWait.Notify(); } -void CombinedUpdateRenderController::AddPerformanceMarker( PerformanceInterface::MarkerType type ) +void CombinedUpdateRenderController::AddPerformanceMarker(PerformanceInterface::MarkerType type) { - if( mPerformanceInterface ) + if(mPerformanceInterface) { - mPerformanceInterface->AddMarker( type ); + mPerformanceInterface->AddMarker(type); } } @@ -942,9 +944,9 @@ void CombinedUpdateRenderController::AddPerformanceMarker( PerformanceInterface: void CombinedUpdateRenderController::PostRenderComplete() { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); mPostRendering = FALSE; - mUpdateRenderThreadWaitCondition.Notify( lock ); + mUpdateRenderThreadWaitCondition.Notify(lock); } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -953,19 +955,19 @@ void CombinedUpdateRenderController::PostRenderComplete() void CombinedUpdateRenderController::PostRenderStarted() { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); mPostRendering = TRUE; } void CombinedUpdateRenderController::PostRenderWaitForCompletion() { - ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); - while( mPostRendering && - ! mNewSurface && // We should NOT wait if we're replacing the surface - ! mDeletedSurface && // We should NOT wait if we're deleting the surface - ! mDestroyUpdateRenderThread ) + ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition); + while(mPostRendering && + !mNewSurface && // We should NOT wait if we're replacing the surface + !mDeletedSurface && // We should NOT wait if we're deleting the surface + !mDestroyUpdateRenderThread) { - mUpdateRenderThreadWaitCondition.Wait( lock ); + mUpdateRenderThreadWaitCondition.Wait(lock); } }