Synchronize the window removal between main thread and render thread 44/209544/4
authorRichard Huang <r.huang@samsung.com>
Mon, 8 Jul 2019 13:09:28 +0000 (14:09 +0100)
committerRichard Huang <r.huang@samsung.com>
Tue, 9 Jul 2019 09:53:34 +0000 (10:53 +0100)
Change-Id: I342dc80ac3c3842b3c7f87423d1cda8cf6d9338d

automated-tests/src/dali/utc-Dali-Scene.cpp
dali/integration-api/core.cpp
dali/integration-api/core.h
dali/internal/common/core-impl.cpp
dali/internal/common/core-impl.h
dali/internal/event/common/scene-impl.cpp
dali/internal/event/common/scene-impl.h
dali/internal/event/rendering/frame-buffer-impl.cpp
dali/internal/event/rendering/frame-buffer-impl.h
dali/internal/render/renderers/render-surface-frame-buffer.cpp
dali/internal/render/renderers/render-surface-frame-buffer.h

index 45eee5c..ebf66d4 100644 (file)
@@ -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;
index 8c27976..596ef9a 100644 (file)
@@ -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();
index f11c187..ff62bcb 100644 (file)
@@ -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
 
   /**
index 8841da4..b906d8f 100644 (file)
@@ -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
index f596ae9..21e0a74 100644 (file)
@@ -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);
index a944d35..19be8cc 100644 (file)
@@ -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()
index fb09efd..6671fa3 100644 (file)
@@ -125,6 +125,11 @@ public:
   void SurfaceResized();
 
   /**
+   * Notify the surface has been deleted.
+   */
+  void SurfaceDeleted();
+
+  /**
    * @copydoc Dali::Integration::Scene::Discard
    */
   void Discard();
index 9c8345d..33afe35 100644 (file)
@@ -125,6 +125,15 @@ void FrameBuffer::SetBackgroundColor( const Vector4& color )
   }
 }
 
+void FrameBuffer::MarkSurfaceAsInvalid()
+{
+  if ( mIsSurfaceBacked )
+  {
+    Render::SurfaceFrameBuffer* renderObject = static_cast<Render::SurfaceFrameBuffer*>( mRenderObject );
+    renderObject->MarkSurfaceAsInvalid();
+  }
+}
+
 FrameBuffer::~FrameBuffer()
 {
   if( EventThreadServices::IsCoreRunning() && mRenderObject )
index 341b284..8484948 100644 (file)
@@ -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
 
   /**
index 4b63c33..2049620 100644 (file)
@@ -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()
index ebe7eb5..7225769 100644 (file)
@@ -17,6 +17,9 @@
  * limitations under the License.
  */
 
+// EXTERNAL INCLUDES
+#include <atomic>
+
 // INTERNAL INCLUDES
 #include <dali/internal/update/manager/update-manager.h>
 #include <dali/internal/render/renderers/render-frame-buffer.h>
@@ -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<bool>           mIsSurfaceInvalid; ///< This is set only from the event thread and read only from the render thread
 };
 
 // Messages for FrameBuffer