X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fadaptor%2Fcommon%2Fcombined-update-render-controller.cpp;h=a0f690e6e15140c0ad84fc48b98127c2d20544f7;hb=95fafbcc37376160061cbf68bffedeae92f945c8;hp=25555a53b7809b69b54ca98785321ddf098231fb;hpb=04584abc7e3d289c06e6fa414c23c8c5baa846be;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 25555a5..a0f690e 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) 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. @@ -21,17 +21,19 @@ // EXTERNAL INCLUDES #include #include +#include // INTERNAL INCLUDES -#include -#include -#include -#include -#include +#include #include +#include +#include #include #include #include +#include +#include +#include namespace Dali { @@ -87,10 +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() ), @@ -106,15 +110,19 @@ CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalS 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( FALSE ), - mForceClear( FALSE ) + mForceClear( FALSE ), + mUploadWithoutRendering( FALSE ), + mFirstFrameAfterResume( FALSE ) { LOG_EVENT_TRACE; @@ -128,10 +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 ); - sem_init( &mEventThreadSemaphore, 0, 0 ); // Initialize to 0 so that it just waits if sem_post has not been called + // 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() @@ -172,7 +182,7 @@ void CombinedUpdateRenderController::Start() sem_wait( &mEventThreadSemaphore ); } - Integration::RenderSurface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); + Dali::RenderSurfaceInterface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); if( currentSurface ) { currentSurface->StartRender(); @@ -182,7 +192,9 @@ void CombinedUpdateRenderController::Start() LOG_EVENT( "Startup Complete, starting Update/Render Thread" ); - RunUpdateRenderThread( CONTINUOUS, false /* No animation progression */ ); + RunUpdateRenderThread( CONTINUOUS, AnimationProgression::NONE, UpdateMode::NORMAL ); + + DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Start\n" ); } void CombinedUpdateRenderController::Pause() @@ -194,6 +206,8 @@ void CombinedUpdateRenderController::Pause() PauseUpdateRenderThread(); AddPerformanceMarker( PerformanceInterface::PAUSED ); + + DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Pause\n" ); } void CombinedUpdateRenderController::Resume() @@ -204,12 +218,19 @@ void CombinedUpdateRenderController::Resume() { LOG_EVENT( "Resuming" ); - RunUpdateRenderThread( CONTINUOUS, true /* Animation progression required while we were paused */ ); + RunUpdateRenderThread( CONTINUOUS, AnimationProgression::USE_ELAPSED_TIME, UpdateMode::NORMAL ); AddPerformanceMarker( PerformanceInterface::RESUME ); mRunning = TRUE; mForceClear = TRUE; + mFirstFrameAfterResume = TRUE; + + DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Resume\n" ); + } + else + { + DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Resume: Already resumed [%d, %d, %d]\n", mRunning, mUpdateRenderRunCount, mUpdateRenderThreadCanSleep ); } } @@ -218,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(); @@ -238,6 +259,8 @@ void CombinedUpdateRenderController::Stop() } mRunning = FALSE; + + DALI_LOG_RELEASE_INFO( "CombinedUpdateRenderController::Stop\n" ); } void CombinedUpdateRenderController::RequestUpdate() @@ -254,14 +277,14 @@ void CombinedUpdateRenderController::RequestUpdate() { LOG_EVENT( "Processing" ); - RunUpdateRenderThread( CONTINUOUS, false /* No animation progression */ ); + RunUpdateRenderThread( CONTINUOUS, AnimationProgression::NONE, UpdateMode::NORMAL ); } ConditionalWait::ScopedLock updateLock( mUpdateRenderThreadWaitCondition ); mPendingRequestUpdate = TRUE; } -void CombinedUpdateRenderController::RequestUpdateOnce() +void CombinedUpdateRenderController::RequestUpdateOnce( UpdateMode updateMode ) { // Increment the update-request count to the maximum if( mUpdateRequestCount < MAXIMUM_UPDATE_REQUESTS ) @@ -269,12 +292,12 @@ void CombinedUpdateRenderController::RequestUpdateOnce() ++mUpdateRequestCount; } - if( IsUpdateRenderThreadPaused() ) + if( IsUpdateRenderThreadPaused() || updateMode == UpdateMode::FORCE_RENDER ) { LOG_EVENT_TRACE; // Run Update/Render once - RunUpdateRenderThread( ONCE, false /* No animation progression */ ); + RunUpdateRenderThread( ONCE, AnimationProgression::NONE, updateMode ); } } @@ -282,23 +305,64 @@ void CombinedUpdateRenderController::ReplaceSurface( Dali::RenderSurfaceInterfac { LOG_EVENT_TRACE; - // Set the ThreadSyncronizationInterface on the new surface - newSurface->SetThreadSynchronization( *this ); + if( mUpdateRenderThread ) + { + // Set the ThreadSyncronizationInterface on the new surface + newSurface->SetThreadSynchronization( *this ); + + LOG_EVENT( "Starting to replace 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 replace the surface now + mNewSurface = newSurface; + mUpdateRenderThreadWaitCondition.Notify( lock ); + } + + // Wait until the surface has been replaced + sem_wait( &mSurfaceSemaphore ); + + LOG_EVENT( "Surface replaced, event-thread continuing" ); + } +} - LOG_EVENT( "Starting to replace the surface, event-thread blocked" ); +void CombinedUpdateRenderController::DeleteSurface( Dali::RenderSurfaceInterface* surface ) +{ + LOG_EVENT_TRACE; - // Start replacing the surface. + if( mUpdateRenderThread ) { - 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 ); + 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 + mDeletedSurface = surface; + mUpdateRenderThreadWaitCondition.Notify( lock ); + } + + // Wait until the surface has been deleted + sem_wait( &mSurfaceSemaphore ); + + LOG_EVENT( "Surface deleted, event-thread continuing" ); } +} - // Wait until the surface has been replaced - sem_wait( &mEventThreadSemaphore ); +void CombinedUpdateRenderController::WaitForGraphicsInitialization() +{ + LOG_EVENT_TRACE; + + if( mUpdateRenderThread ) + { + LOG_EVENT( "Waiting for graphics initialisation, event-thread blocked" ); - LOG_EVENT( "Surface replaced, event-thread continuing" ); + // Wait until the graphics has been initialised + sem_wait( &mGraphicsInitializeSemaphore ); + + LOG_EVENT( "graphics initialised, event-thread continuing" ); + } } void CombinedUpdateRenderController::ResizeSurface() @@ -339,16 +403,50 @@ 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 /////////////////////////////////////////////////////////////////////////////////////////////////// -void CombinedUpdateRenderController::RunUpdateRenderThread( int numberOfCycles, bool useElapsedTime ) +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 = useElapsedTime; + mUploadWithoutRendering = ( updateMode == UpdateMode::SKIP_RENDER ); LOG_COUNTER_EVENT( "mUpdateRenderRunCount: %d, mUseElapsedTimeAfterWait: %d", mUpdateRenderRunCount, mUseElapsedTimeAfterWait ); mUpdateRenderThreadWaitCondition.Notify( lock ); } @@ -369,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 } @@ -414,9 +518,10 @@ void CombinedUpdateRenderController::UpdateRenderThread() Dali::DisplayConnection& displayConnection = mAdaptorInterfaces.GetDisplayConnectionInterface(); displayConnection.Initialize(); - RenderSurfaceInterface* currentSurface = nullptr; + // EGL has been initialised at this point + NotifyGraphicsInitialised(); -#if DALI_GLES_VERSION >= 30 + RenderSurfaceInterface* currentSurface = nullptr; GraphicsInterface& graphics = mAdaptorInterfaces.GetGraphicsInterface(); EglGraphics* eglGraphics = static_cast(&graphics); @@ -425,22 +530,40 @@ void CombinedUpdateRenderController::UpdateRenderThread() EglInterface* eglInterface = &eglGraphics->GetEglInterface(); Internal::Adaptor::EglImplementation& eglImpl = static_cast( *eglInterface ); - eglImpl.ChooseConfig( true, COLOR_DEPTH_32 ); // Always use this for shared context??? - // Create a surfaceless OpenGL context for shared resources - eglImpl.CreateContext(); - eglImpl.MakeContextCurrent( EGL_NO_SURFACE, eglImpl.GetContext() ); + // 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 ); + } -#else // DALI_GLES_VERSION >= 30 + // Check whether surfaceless context is supported + bool isSurfacelessContextSupported = eglImpl.IsSurfacelessContextSupported(); + eglGraphics->SetIsSurfacelessContextSupported( isSurfacelessContextSupported ); - currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface(); - if( currentSurface ) + if ( isSurfacelessContextSupported ) { - currentSurface->InitializeGraphics(); - currentSurface->MakeContextCurrent(); + // 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(); + } } -#endif + GlImplementation& gles = eglGraphics->GetGlesInterface(); + gles.ContextCreated(); + eglGraphics->SetGlesVersion( gles.GetGlesVersion() ); // Tell core it has a context mCore.ContextCreated(); @@ -472,7 +595,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() ) @@ -487,19 +610,21 @@ void CombinedUpdateRenderController::UpdateRenderThread() // REPLACE SURFACE ////////////////////////////// - Integration::RenderSurface* newSurface = ShouldSurfaceBeReplaced(); + Dali::RenderSurfaceInterface* newSurface = ShouldSurfaceBeReplaced(); if( DALI_UNLIKELY( newSurface ) ) { 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->ReplaceGraphicsSurface(); + newSurface->MakeContextCurrent(); + // TODO: ReplaceGraphicsSurface doesn't work, InitializeGraphics() + // already creates new surface window, the surface and the context. + // We probably don't need ReplaceGraphicsSurface at all. + // newSurface->ReplaceGraphicsSurface(); SurfaceReplaced(); } @@ -517,6 +642,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; @@ -545,6 +680,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() } // Check resize + bool surfaceResized = false; bool shouldSurfaceBeResized = ShouldSurfaceBeResized(); if( DALI_UNLIKELY( shouldSurfaceBeResized ) ) { @@ -552,6 +688,7 @@ void CombinedUpdateRenderController::UpdateRenderThread() { LOG_UPDATE_RENDER_TRACE_FMT( "Resizing Surface" ); SurfaceResized(); + surfaceResized = true; } } @@ -574,15 +711,90 @@ void CombinedUpdateRenderController::UpdateRenderThread() } } -#if DALI_GLES_VERSION >= 30 - // Make the shared surfaceless context as current before rendering - eglImpl.MakeContextCurrent( EGL_NO_SURFACE, eglImpl.GetContext() ); -#endif + if( eglImpl.IsSurfacelessContextSupported() ) + { + // Make the shared surfaceless context as current before rendering + eglImpl.MakeContextCurrent( EGL_NO_SURFACE, eglImpl.GetContext() ); + } + + 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(); + mFirstFrameAfterResume = FALSE; + } Integration::RenderStatus renderStatus; AddPerformanceMarker( PerformanceInterface::RENDER_START ); - mCore.Render( renderStatus, mForceClear ); + + // 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 + ////////////////////////////// + + Dali::RenderSurfaceInterface* deletedSurface = ShouldSurfaceBeDeleted(); + if( DALI_UNLIKELY( deletedSurface ) ) + { + LOG_UPDATE_RENDER_TRACE_FMT( "Deleting Surface" ); + + deletedSurface->DestroySurface(); + + SurfaceDeleted(); + } + AddPerformanceMarker( PerformanceInterface::RENDER_END ); mForceClear = false; @@ -643,15 +855,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 @@ -667,12 +886,14 @@ bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bo ( 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 ); // Reset the time when the thread is waiting, so the sleep-until time for @@ -692,6 +913,7 @@ bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bo 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; @@ -709,11 +931,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; @@ -722,7 +944,23 @@ Integration::RenderSurface* CombinedUpdateRenderController::ShouldSurfaceBeRepla void CombinedUpdateRenderController::SurfaceReplaced() { // Just increment the semaphore - sem_post( &mEventThreadSemaphore ); + sem_post( &mSurfaceSemaphore ); +} + +Dali::RenderSurfaceInterface* CombinedUpdateRenderController::ShouldSurfaceBeDeleted() +{ + ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); + + Dali::RenderSurfaceInterface* deletedSurface = mDeletedSurface; + mDeletedSurface = NULL; + + return deletedSurface; +} + +void CombinedUpdateRenderController::SurfaceDeleted() +{ + // Just increment the semaphore + sem_post( &mSurfaceSemaphore ); } bool CombinedUpdateRenderController::ShouldSurfaceBeResized() @@ -747,6 +985,11 @@ void CombinedUpdateRenderController::NotifyThreadInitialised() sem_post( &mEventThreadSemaphore ); } +void CombinedUpdateRenderController::NotifyGraphicsInitialised() +{ + sem_post( &mGraphicsInitializeSemaphore ); +} + void CombinedUpdateRenderController::AddPerformanceMarker( PerformanceInterface::MarkerType type ) { if( mPerformanceInterface ) @@ -781,7 +1024,7 @@ void CombinedUpdateRenderController::PostRenderWaitForCompletion() ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition ); while( mPostRendering && ! mNewSurface && // We should NOT wait if we're replacing the surface - ! mSurfaceResized && // We should NOT wait if we're resizing the surface + ! mDeletedSurface && // We should NOT wait if we're deleting the surface ! mDestroyUpdateRenderThread ) { mUpdateRenderThreadWaitCondition.Wait( lock );