Remove EGL surface in the update thread 39/234139/1
authorHeeyong Song <heeyong.song@samsung.com>
Wed, 13 May 2020 07:30:29 +0000 (16:30 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Fri, 22 May 2020 06:49:23 +0000 (15:49 +0900)
Change-Id: Id29847f34c1094dc7ddc44b2afbff2ddb6f0d020

dali/integration-api/adaptor-framework/scene-holder-impl.cpp
dali/internal/adaptor/common/adaptor-impl.cpp
dali/internal/adaptor/common/adaptor-impl.h
dali/internal/adaptor/common/combined-update-render-controller.cpp
dali/internal/adaptor/common/combined-update-render-controller.h
dali/internal/adaptor/common/thread-controller-interface.h
dali/internal/system/common/thread-controller.cpp
dali/internal/system/common/thread-controller.h
dali/internal/window-system/common/window-impl.cpp
dali/internal/window-system/common/window-render-surface.cpp

index 2440b355d0f1bbbff334aaf600e05da9403dcd24..7162a1c715d5b2317faf0c715e602307730ef13f 100644 (file)
@@ -133,6 +133,8 @@ SceneHolder::~SceneHolder()
     mAdaptor->RemoveObserver( *mLifeCycleObserver.get() );
     mAdaptor->RemoveWindow( this );
 
+    mAdaptor->DeleteSurface( *mSurface.get() );
+
     mAdaptor = nullptr;
   }
 
index 516e30f87991025e9491ce3be8b157e17c8766a4..737845d2aae3ce626b3efc79e80834914d2994b0 100755 (executable)
@@ -558,6 +558,16 @@ void Adaptor::ReplaceSurface( Dali::Integration::SceneHolder window, Dali::Rende
   }
 }
 
+void Adaptor::DeleteSurface( Dali::RenderSurfaceInterface& surface )
+{
+  // Flush the event queue to give the update-render thread chance
+  // to start processing messages for new camera setup etc as soon as possible
+  ProcessCoreEvents();
+
+  // This method blocks until the render thread has finished rendering the current surface.
+  mThreadController->DeleteSurface( &surface );
+}
+
 Dali::RenderSurfaceInterface& Adaptor::GetSurface() const
 {
   return *mWindows.front()->GetSurface();
@@ -1043,11 +1053,6 @@ bool Adaptor::IsMultipleWindowSupported() const
   return mConfigurationManager->IsMultipleWindowSupported();
 }
 
-bool Adaptor::IsRenderingWindows() const
-{
-  return ( mThreadController && mThreadController->IsRenderingWindows() );
-}
-
 void Adaptor::RequestUpdateOnce()
 {
   if( mThreadController )
index 09017c6aa920724488e9aee5dba074b86f89406f..9e4c079ae65c3539367d315bd75ad92ecc87f586 100755 (executable)
@@ -291,6 +291,12 @@ public: // AdaptorInternalServices implementation
    */
   bool RemoveWindow( Dali::Internal::Adaptor::SceneHolder* childWindow );
 
+  /**
+   * @brief Deletes the rendering surface
+   * @param[in] surface to delete
+   */
+  void DeleteSurface( Dali::RenderSurfaceInterface& surface );
+
   /**
    * @brief Retrieve the window that the given actor is added to.
    *
@@ -443,13 +449,6 @@ public:
    */
   bool IsMultipleWindowSupported() const;
 
-  /**
-   * @brief Checks whether the windows are being rendered in the render thread.
-   *
-   * @return true if the windows are being rendered in the render thread, or false if not.
-   */
-  bool IsRenderingWindows() const;
-
 public:  //AdaptorInternalServices
 
   /**
index e80312eec175bce89d220614920204e5d65b62be..5c5840a06a75a64793de2bb9db56a6219c9d9c47 100644 (file)
@@ -115,12 +115,12 @@ CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalS
   mPendingRequestUpdate( FALSE ),
   mUseElapsedTimeAfterWait( FALSE ),
   mNewSurface( NULL ),
+  mDeletedSurface( nullptr ),
   mPostRendering( FALSE ),
   mSurfaceResized( FALSE ),
   mForceClear( FALSE ),
   mUploadWithoutRendering( FALSE ),
-  mFirstFrameAfterResume( FALSE ),
-  mIsRenderingWindows( false )
+  mFirstFrameAfterResume( FALSE )
 {
   LOG_EVENT_TRACE;
 
@@ -324,6 +324,29 @@ void CombinedUpdateRenderController::ReplaceSurface( Dali::RenderSurfaceInterfac
   }
 }
 
+void CombinedUpdateRenderController::DeleteSurface( Dali::RenderSurfaceInterface* surface )
+{
+  LOG_EVENT_TRACE;
+
+  if( mUpdateRenderThread )
+  {
+    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( &mEventThreadSemaphore );
+
+    LOG_EVENT( "Surface deleted, event-thread continuing" );
+  }
+}
+
 void CombinedUpdateRenderController::WaitForGraphicsInitialization()
 {
   LOG_EVENT_TRACE;
@@ -663,8 +686,6 @@ void CombinedUpdateRenderController::UpdateRenderThread()
 
     AddPerformanceMarker( PerformanceInterface::RENDER_START );
 
-    mIsRenderingWindows = true;
-
     // Upload shared resources
     mCore.PreRender( renderStatus, mForceClear, mUploadWithoutRendering );
 
@@ -676,33 +697,42 @@ void CombinedUpdateRenderController::UpdateRenderThread()
 
       for( auto&& window : windows )
       {
-        if ( window && !window->IsBeingDeleted() )
-        {
-          Dali::Integration::Scene scene = window->GetScene();
-          Dali::RenderSurfaceInterface* windowSurface = window->GetSurface();
+        Dali::Integration::Scene scene = window->GetScene();
+        Dali::RenderSurfaceInterface* windowSurface = window->GetSurface();
 
-          if ( scene && windowSurface )
-          {
-            windowSurface->InitializeGraphics();
+        if ( scene && windowSurface )
+        {
+          windowSurface->InitializeGraphics();
 
-            // Render off-screen frame buffers first if any
-            mCore.RenderScene( scene, true );
+          // Render off-screen frame buffers first if any
+          mCore.RenderScene( scene, true );
 
-            // Switch to the EGL context of the surface
-            windowSurface->PreRender( surfaceResized ); // Switch GL context
+          // Switch to the EGL context of the surface
+          windowSurface->PreRender( surfaceResized ); // Switch GL context
 
-            // Render the surface
-            mCore.RenderScene( scene, false );
+          // Render the surface
+          mCore.RenderScene( scene, false );
 
-            windowSurface->PostRender( false, false, surfaceResized ); // Swap Buffer
-          }
+          windowSurface->PostRender( false, false, surfaceResized ); // Swap Buffer
         }
       }
     }
 
     mCore.PostRender( mUploadWithoutRendering );
 
-    mIsRenderingWindows = false;
+    //////////////////////////////
+    // DELETE SURFACE
+    //////////////////////////////
+
+    Dali::RenderSurfaceInterface* deletedSurface = ShouldSurfaceBeDeleted();
+    if( DALI_UNLIKELY( deletedSurface ) )
+    {
+      LOG_UPDATE_RENDER_TRACE_FMT( "Deleting Surface" );
+
+      deletedSurface->DestroySurface();
+
+      SurfaceDeleted();
+    }
 
     AddPerformanceMarker( PerformanceInterface::RENDER_END );
 
@@ -791,12 +821,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
@@ -816,6 +848,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;
@@ -849,6 +882,22 @@ void CombinedUpdateRenderController::SurfaceReplaced()
   sem_post( &mEventThreadSemaphore );
 }
 
+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( &mEventThreadSemaphore );
+}
+
 bool CombinedUpdateRenderController::ShouldSurfaceBeResized()
 {
   ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
@@ -910,6 +959,7 @@ 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 )
   {
     mUpdateRenderThreadWaitCondition.Wait( lock );
index ca225170d7d8258e10f5f1cc80d56b5af7963726..54cc67d6af86a60d43f9309facee11d3dec4fcfc 100644 (file)
@@ -127,6 +127,11 @@ public:
    */
   virtual void ReplaceSurface( Dali::RenderSurfaceInterface* surface );
 
+  /**
+   * @copydoc ThreadControllerInterface::DeleteSurface()
+   */
+  virtual void DeleteSurface( Dali::RenderSurfaceInterface* surface );
+
   /**
    * @copydoc ThreadControllerInterface::ResizeSurface()
    */
@@ -152,11 +157,6 @@ public:
    */
   virtual void AddSurface( Dali::RenderSurfaceInterface* surface );
 
-  /**
-   * @copydoc ThreadControllerInterface::IsRenderingWindows()
-   */
-  bool IsRenderingWindows() const override { return mIsRenderingWindows; }
-
 private:
 
   // Undefined copy constructor.
@@ -249,6 +249,21 @@ private:
    */
   void SurfaceReplaced();
 
+  /**
+   * Checks to see if the surface needs to be deleted.
+   * This will lock the mutex in mUpdateRenderThreadWaitCondition.
+   *
+   * @return Pointer to the deleted surface, nullptr otherwise
+   */
+  Dali::RenderSurfaceInterface* ShouldSurfaceBeDeleted();
+
+  /**
+   * Called by the Update/Render thread after a surface has been deleted.
+   *
+   * This will lock the mutex in mEventThreadWaitCondition
+   */
+  void SurfaceDeleted();
+
   /**
    * Checks to see if the surface needs to be resized.
    * This will lock the mutex in mUpdateRenderThreadWaitCondition.
@@ -365,6 +380,7 @@ private:
   volatile unsigned int             mUseElapsedTimeAfterWait;          ///< Whether we should use the elapsed time after waiting (set by the event-thread, read by the update-render-thread).
 
   Dali::RenderSurfaceInterface* volatile mNewSurface;                  ///< Will be set to the new-surface if requested (set by the event-thread, read & cleared by the update-render thread).
+  Dali::RenderSurfaceInterface* volatile mDeletedSurface;              ///< Will be set to the deleted surface if requested (set by the event-thread, read & cleared by the update-render thread).
 
   volatile unsigned int             mPostRendering;                    ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
   volatile unsigned int             mSurfaceResized;                   ///< Will be set to resize the surface (set by the event-thread, read & cleared by the update-render thread).
@@ -373,8 +389,6 @@ private:
   volatile unsigned int             mUploadWithoutRendering;           ///< Will be set to upload the resource only (with no rendering)
 
   volatile unsigned int             mFirstFrameAfterResume;            ///< Will be set to check the first frame after resume (for log)
-
-  std::atomic<bool>                 mIsRenderingWindows;               ///< This is set only from the render thread and read only from the event thread
 };
 
 } // namespace Adaptor
index 94276ff31b0201a6b387b96dbceb24d4ac213ca1..6b9055bcd87c523529c11117d5a993a694e96657 100644 (file)
@@ -92,6 +92,12 @@ public:
    */
   virtual void ReplaceSurface( Dali::RenderSurfaceInterface* surface ) = 0;
 
+  /**
+   * Deletes the surface.
+   * @param[in] surface The surface to be deleted
+   */
+  virtual void DeleteSurface( Dali::RenderSurfaceInterface* surface ) = 0;
+
   /**
    * Resize the surface.
    */
@@ -118,11 +124,6 @@ public:
    */
   virtual void AddSurface( Dali::RenderSurfaceInterface* surface ) = 0;
 
-  /**
-   * @copydoc Dali::Adaptor::IsRenderingWindows()
-   */
-  virtual bool IsRenderingWindows() const = 0;
-
 protected:
 
   /**
index 605c76ddcc897892933abf73e9f8321e9881c926..a9054ec9ac8ca6c96f918133d27654aaa64b2a13 100644 (file)
@@ -90,6 +90,11 @@ void ThreadController::ReplaceSurface( Dali::RenderSurfaceInterface* newSurface
   mThreadControllerInterface->ReplaceSurface( newSurface );
 }
 
+void ThreadController::DeleteSurface( Dali::RenderSurfaceInterface* surface )
+{
+  mThreadControllerInterface->DeleteSurface( surface );
+}
+
 void ThreadController::ResizeSurface()
 {
   mThreadControllerInterface->ResizeSurface();
@@ -115,11 +120,6 @@ void ThreadController::AddSurface( Dali::RenderSurfaceInterface* newSurface )
   mThreadControllerInterface->AddSurface( newSurface );
 }
 
-bool ThreadController::IsRenderingWindows() const
-{
-  return mThreadControllerInterface->IsRenderingWindows();
-}
-
 } // namespace Adaptor
 
 } // namespace Internal
index 471a5f93d5d8d391619d712a5a6ea553261dcbcf..c4f3961c84c20a141037bf0667e87be9dbc343e6 100644 (file)
@@ -111,6 +111,12 @@ public:
    */
   void ReplaceSurface( Dali::RenderSurfaceInterface* surface );
 
+  /**
+   * Deletes the surface.
+   * @param surface The surface to be deleted
+   */
+  void DeleteSurface( Dali::RenderSurfaceInterface* surface );
+
   /**
    * Resize the surface.
    */
@@ -138,11 +144,6 @@ public:
    */
   void AddSurface( Dali::RenderSurfaceInterface* surface );
 
-  /**
-   * @copydoc Dali::Adaptor::IsRenderingWindows()
-   */
-  bool IsRenderingWindows() const;
-
 private:
 
   // Undefined copy constructor.
index 69ba1d92888ac39bb0af2fd536010c9a605d66f8..b21ca778ff6e85779b7807396c530cdea02aec86 100755 (executable)
@@ -99,13 +99,6 @@ Window::Window()
 
 Window::~Window()
 {
-  mIsBeingDeleted = true;
-
-  while ( mAdaptor && mAdaptor->IsRenderingWindows() )
-  {
-    std::this_thread::yield(); // to allow other threads to run
-  }
-
   if ( mEventHandler )
   {
     mEventHandler->RemoveObserver( *this );
index e1a344f6c2bb36b301a51f7da64bc34005c2ce10..c95d5082e5dafb13b2827cabdcd4f184c9c0e566 100644 (file)
@@ -85,11 +85,6 @@ WindowRenderSurface::~WindowRenderSurface()
   {
     delete mRotationTrigger;
   }
-
-  if ( mEGLSurface )
-  {
-    DestroySurface();
-  }
 }
 
 void WindowRenderSurface::Initialize( Any surface )
@@ -264,7 +259,13 @@ void WindowRenderSurface::DestroySurface()
     DALI_LOG_RELEASE_INFO("WindowRenderSurface::DestroySurface: WinId (%d)\n", mWindowBase->GetNativeWindowId() );
 
     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+
     eglImpl.DestroySurface( mEGLSurface );
+    mEGLSurface = nullptr;
+
+    // Destroy context also
+    eglImpl.DestroyContext( mEGLContext );
+    mEGLContext = nullptr;
 
     mWindowBase->DestroyEglWindow();
   }