From: Richard Huang Date: Mon, 8 Jul 2019 13:09:28 +0000 (+0100) Subject: Synchronize the window removal between main thread and render thread X-Git-Tag: dali_1.4.28~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-core.git;a=commitdiff_plain;h=caa9d214b3e34809fd6fabfd4caa289c564416fe Synchronize the window removal between main thread and render thread Change-Id: I342dc80ac3c3842b3c7f87423d1cda8cf6d9338d --- diff --git a/automated-tests/src/dali/utc-Dali-Scene.cpp b/automated-tests/src/dali/utc-Dali-Scene.cpp index 45eee5c..ebf66d4 100644 --- a/automated-tests/src/dali/utc-Dali-Scene.cpp +++ b/automated-tests/src/dali/utc-Dali-Scene.cpp @@ -483,6 +483,44 @@ int UtcDaliSceneRootLayerAndSceneAlignment(void) END_TEST; } +int UtcDaliSceneDeleteSurface(void) +{ + TestApplication application; + + // Create a Scene + Dali::Integration::Scene scene = Dali::Integration::Scene::New( Vector2( 480.0f, 800.0f ) ); + DALI_TEST_CHECK( scene ); + + // Create the render surface for the scene + TestRenderSurface* renderSurface = new TestRenderSurface( Dali::PositionSize( 0, 0, 480.0f, 800.0f ) ); + scene.SetSurface( *renderSurface ); + + // Render and notify. + application.SendNotification(); + application.Render(0); + + // Add a renderable actor to the scene + auto actor = CreateRenderableActor(); + scene.Add( actor ); + + // Render and notify. + application.SendNotification(); + application.Render(0); + + // Notify the Core that the render surface will be deleted. + application.GetCore().SurfaceDeleted( renderSurface ); + + // Delete the render surface + delete renderSurface; + renderSurface = nullptr; + + // Render and notify. + application.SendNotification(); + application.Render(0); + + END_TEST; +} + int UtcDaliSceneEventProcessingFinishedP(void) { TestApplication application; diff --git a/dali/integration-api/core.cpp b/dali/integration-api/core.cpp index 8c27976..596ef9a 100644 --- a/dali/integration-api/core.cpp +++ b/dali/integration-api/core.cpp @@ -91,6 +91,11 @@ void Core::SurfaceResized( Integration::RenderSurface* surface ) mImpl->SurfaceResized(surface); } +void Core::SurfaceDeleted( Integration::RenderSurface* surface ) +{ + mImpl->SurfaceDeleted(surface); +} + void Core::SceneCreated() { mImpl->SceneCreated(); diff --git a/dali/integration-api/core.h b/dali/integration-api/core.h index f11c187..ff62bcb 100644 --- a/dali/integration-api/core.h +++ b/dali/integration-api/core.h @@ -294,6 +294,13 @@ public: */ void SurfaceResized( Integration::RenderSurface* surface ); + /** + * Notify the Core that the GL surface has been deleted. + * Multi-threading note: this method should be called from the main thread + * @param[in] surface The deleted surface + */ + void SurfaceDeleted( Integration::RenderSurface* surface ); + // Core Lifecycle /** diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp index 8841da4..b906d8f 100644 --- a/dali/internal/common/core-impl.cpp +++ b/dali/internal/common/core-impl.cpp @@ -202,6 +202,18 @@ void Core::SurfaceResized( Integration::RenderSurface* surface ) } } +void Core::SurfaceDeleted( Integration::RenderSurface* surface ) +{ + for( auto scene : mScenes ) + { + if( scene->GetSurface() == surface ) + { + scene->SurfaceDeleted(); + break; + } + } +} + void Core::Update( float elapsedSeconds, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds, Integration::UpdateStatus& status, bool renderToFboEnabled, bool isRenderingToFbo ) { // set the time delta so adaptor can easily print FPS with a release build with 0 as diff --git a/dali/internal/common/core-impl.h b/dali/internal/common/core-impl.h index f596ae9..21e0a74 100644 --- a/dali/internal/common/core-impl.h +++ b/dali/internal/common/core-impl.h @@ -124,6 +124,11 @@ public: void SurfaceResized( Integration::RenderSurface* surface ); /** + * @copydoc Dali::Integration::Core::SurfaceDeleted(Integration::RenderSurface*) + */ + void SurfaceDeleted( Integration::RenderSurface* surface ); + + /** * @copydoc Dali::Integration::Core::SetMinimumFrameTimeInterval(uint32_t) */ void SetMinimumFrameTimeInterval(uint32_t interval); diff --git a/dali/internal/event/common/scene-impl.cpp b/dali/internal/event/common/scene-impl.cpp index a944d35..19be8cc 100644 --- a/dali/internal/event/common/scene-impl.cpp +++ b/dali/internal/event/common/scene-impl.cpp @@ -90,6 +90,11 @@ Scene::~Scene() mRenderTaskList.Reset(); } + if ( mFrameBuffer ) + { + mFrameBuffer.Reset(); + } + // Discard this Scene from the Core Discard(); } @@ -247,6 +252,15 @@ void Scene::SurfaceResized() } } +void Scene::SurfaceDeleted() +{ + if ( mFrameBuffer ) + { + // The frame buffer doesn't have a valid render surface any more. + mFrameBuffer->MarkSurfaceAsInvalid(); + } +} + Integration::RenderSurface* Scene::GetSurface() const { return mSurface; @@ -304,23 +318,42 @@ Vector4 Scene::GetBackgroundColor() const void Scene::EmitKeyEventSignal(const KeyEvent& event) { - mKeyEventSignal.Emit( event ); + if ( !mKeyEventSignal.Empty() ) + { + Dali::Integration::Scene handle( this ); + mKeyEventSignal.Emit( event ); + } } void Scene::EmitEventProcessingFinishedSignal() { - mEventProcessingFinishedSignal.Emit(); + if ( !mEventProcessingFinishedSignal.Empty() ) + { + Dali::Integration::Scene handle( this ); + mEventProcessingFinishedSignal.Emit(); + } } void Scene::EmitTouchedSignal( const TouchEvent& touchEvent, const Dali::TouchData& touch ) { - mTouchedSignal.Emit( touchEvent ); - mTouchSignal.Emit( touch ); + Dali::Integration::Scene handle( this ); + if ( !mTouchedSignal.Empty() ) + { + mTouchedSignal.Emit( touchEvent ); + } + if ( !mTouchSignal.Empty() ) + { + mTouchSignal.Emit( touch ); + } } void Scene::EmitWheelEventSignal(const WheelEvent& event) { - mWheelEventSignal.Emit( event ); + if ( !mWheelEventSignal.Empty() ) + { + Dali::Integration::Scene handle( this ); + mWheelEventSignal.Emit( event ); + } } Integration::Scene::KeyEventSignalType& Scene::KeyEventSignal() diff --git a/dali/internal/event/common/scene-impl.h b/dali/internal/event/common/scene-impl.h index fb09efd..6671fa3 100644 --- a/dali/internal/event/common/scene-impl.h +++ b/dali/internal/event/common/scene-impl.h @@ -125,6 +125,11 @@ public: void SurfaceResized(); /** + * Notify the surface has been deleted. + */ + void SurfaceDeleted(); + + /** * @copydoc Dali::Integration::Scene::Discard */ void Discard(); diff --git a/dali/internal/event/rendering/frame-buffer-impl.cpp b/dali/internal/event/rendering/frame-buffer-impl.cpp index 9c8345d..33afe35 100644 --- a/dali/internal/event/rendering/frame-buffer-impl.cpp +++ b/dali/internal/event/rendering/frame-buffer-impl.cpp @@ -125,6 +125,15 @@ void FrameBuffer::SetBackgroundColor( const Vector4& color ) } } +void FrameBuffer::MarkSurfaceAsInvalid() +{ + if ( mIsSurfaceBacked ) + { + Render::SurfaceFrameBuffer* renderObject = static_cast( mRenderObject ); + renderObject->MarkSurfaceAsInvalid(); + } +} + FrameBuffer::~FrameBuffer() { if( EventThreadServices::IsCoreRunning() && mRenderObject ) diff --git a/dali/internal/event/rendering/frame-buffer-impl.h b/dali/internal/event/rendering/frame-buffer-impl.h index 341b284..8484948 100644 --- a/dali/internal/event/rendering/frame-buffer-impl.h +++ b/dali/internal/event/rendering/frame-buffer-impl.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_FRAME_BUFFER_H /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 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. @@ -104,6 +104,16 @@ public: */ void SetBackgroundColor( const Vector4& color ); + /** + * @brief Mark the render surface as invalid + * + * The render surface is maked as invalid when it is deleted. + * + * @note Only for FrameBuffer backed by a render surface. + * @return True if the FrameBuffer is backed by a render surface + */ + void MarkSurfaceAsInvalid(); + private: // implementation /** diff --git a/dali/internal/render/renderers/render-surface-frame-buffer.cpp b/dali/internal/render/renderers/render-surface-frame-buffer.cpp index 4b63c33..2049620 100644 --- a/dali/internal/render/renderers/render-surface-frame-buffer.cpp +++ b/dali/internal/render/renderers/render-surface-frame-buffer.cpp @@ -34,7 +34,8 @@ SurfaceFrameBuffer::SurfaceFrameBuffer( Integration::RenderSurface* surface ) mWidth( mSurface->GetPositionSize().width ), mHeight( mSurface->GetPositionSize().height ), mBackgroundColor( 0.f, 0.f, 0.f, 1.f ), - mSizeChanged( false ) + mSizeChanged( false ), + mIsSurfaceInvalid( false ) { } @@ -43,6 +44,11 @@ SurfaceFrameBuffer::~SurfaceFrameBuffer() void SurfaceFrameBuffer::Destroy( Context& context ) { + if ( mSurface && !mIsSurfaceInvalid ) + { + mSurface->DestroySurface(); + mSurface = nullptr; + } } void SurfaceFrameBuffer::GlContextDestroyed() @@ -51,20 +57,33 @@ void SurfaceFrameBuffer::GlContextDestroyed() { mContext->GlContextDestroyed(); } + + if ( mSurface && !mIsSurfaceInvalid ) + { + mSurface->DestroySurface(); + mSurface = nullptr; + } } void SurfaceFrameBuffer::Initialize(Context& context) { mContext = &context; mContext->GlContextCreated(); - mSurface->InitializeGraphics(); + + if ( mSurface && !mIsSurfaceInvalid ) + { + mSurface->InitializeGraphics(); + } } void SurfaceFrameBuffer::Bind( Context& context ) { - mSurface->PreRender( mSizeChanged ); + if ( mSurface && !mIsSurfaceInvalid ) + { + mSurface->PreRender( mSizeChanged ); - context.BindFramebuffer( GL_FRAMEBUFFER, 0u ); + context.BindFramebuffer( GL_FRAMEBUFFER, 0u ); + } } uint32_t SurfaceFrameBuffer::GetWidth() const @@ -79,7 +98,10 @@ uint32_t SurfaceFrameBuffer::GetHeight() const void SurfaceFrameBuffer::PostRender() { - mSurface->PostRender( false, false, mSizeChanged ); + if ( mSurface && !mIsSurfaceInvalid ) + { + mSurface->PostRender( false, false, mSizeChanged ); + } mSizeChanged = false; } @@ -91,12 +113,12 @@ Context* SurfaceFrameBuffer::GetContext() Integration::DepthBufferAvailable SurfaceFrameBuffer::GetDepthBufferRequired() { - return mSurface->GetDepthBufferRequired(); + return mSurface && !mIsSurfaceInvalid ? Integration::DepthBufferAvailable::FALSE : mSurface->GetDepthBufferRequired(); } Integration::StencilBufferAvailable SurfaceFrameBuffer::GetStencilBufferRequired() { - return mSurface->GetStencilBufferRequired(); + return mSurface && !mIsSurfaceInvalid ? Integration::StencilBufferAvailable::TRUE : mSurface->GetStencilBufferRequired(); } Vector4 SurfaceFrameBuffer::GetBackgroundColor() diff --git a/dali/internal/render/renderers/render-surface-frame-buffer.h b/dali/internal/render/renderers/render-surface-frame-buffer.h index ebe7eb5..7225769 100644 --- a/dali/internal/render/renderers/render-surface-frame-buffer.h +++ b/dali/internal/render/renderers/render-surface-frame-buffer.h @@ -17,6 +17,9 @@ * limitations under the License. */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include @@ -96,6 +99,11 @@ public: */ void SetBackgroundColor( const Vector4& color ); + /** + * @copydoc Dali::Internal::FrameBuffer::MarkSurfaceAsInvalid() + */ + void MarkSurfaceAsInvalid() { mIsSurfaceInvalid = true; }; + public: /** @@ -136,6 +144,7 @@ private: uint32_t mHeight; Vector4 mBackgroundColor; bool mSizeChanged; + std::atomic mIsSurfaceInvalid; ///< This is set only from the event thread and read only from the render thread }; // Messages for FrameBuffer