Pixmap render surface synchronization moved to thread-synchronization 83/46983/5
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 27 Aug 2015 16:07:31 +0000 (17:07 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 28 Aug 2015 17:21:32 +0000 (18:21 +0100)
Change-Id: If4d63d53795047a4ddb65e09cb080ab7316fa35e

14 files changed:
adaptors/base/thread-controller.cpp
adaptors/base/thread-synchronization.cpp
adaptors/base/thread-synchronization.h
adaptors/devel-api/adaptor-framework/render-surface.h
adaptors/integration-api/file.list
adaptors/integration-api/thread-synchronization-interface.h [new file with mode: 0644]
adaptors/integration-api/wayland/pixmap-render-surface.h
adaptors/integration-api/x11/pixmap-render-surface.h
adaptors/wayland/pixmap-render-surface-wl.cpp
adaptors/wayland/window-render-surface-wl.cpp
adaptors/wayland/window-render-surface.h
adaptors/x11/pixmap-render-surface-x.cpp
adaptors/x11/window-render-surface-x.cpp
adaptors/x11/window-render-surface.h

index ad31ad8..1640c8d 100644 (file)
@@ -35,8 +35,7 @@ namespace Internal
 namespace Adaptor
 {
 
-ThreadController::ThreadController( AdaptorInternalServices& adaptorInterfaces,
-                                                const EnvironmentOptions& environmentOptions )
+ThreadController::ThreadController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions )
 : mAdaptorInterfaces( adaptorInterfaces ),
   mUpdateThread( NULL ),
   mRenderThread( NULL ),
@@ -51,6 +50,13 @@ ThreadController::ThreadController( AdaptorInternalServices& adaptorInterfaces,
   mRenderThread = new RenderThread( *mThreadSync, adaptorInterfaces, environmentOptions );
 
   mVSyncNotifier = new VSyncNotifier( *mThreadSync, adaptorInterfaces, environmentOptions );
+
+  // Set the thread-synchronization interface on the render-surface
+  RenderSurface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface();
+  if( currentSurface )
+  {
+    currentSurface->SetThreadSynchronization( *mThreadSync );
+  }
 }
 
 ThreadController::~ThreadController()
@@ -110,6 +116,9 @@ void ThreadController::RequestUpdateOnce()
 
 void ThreadController::ReplaceSurface( RenderSurface* newSurface )
 {
+  // Set the thread-syncronization on the new surface
+  newSurface->SetThreadSynchronization( *mThreadSync );
+
   // tell render thread to start the replace. This call will block until the replace
   // has completed.
   RenderSurface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface();
index f925a27..933346e 100644 (file)
@@ -60,6 +60,7 @@ ThreadSynchronization::ThreadSynchronization( AdaptorInternalServices& adaptorIn
   mVSyncThreadStop( FALSE ),
   mRenderThreadStop( FALSE ),
   mRenderThreadReplacingSurface( FALSE ),
+  mRenderThreadSurfaceRendered( FALSE ),
   mEventThreadSurfaceReplaced( FALSE ),
   mVSyncThreadInitialised( FALSE ),
   mRenderThreadInitialised( FALSE ),
@@ -475,8 +476,11 @@ bool ThreadSynchronization::RenderReady( RenderRequest*& requestPtr )
       ConditionalWait::ScopedLock renderLock( mRenderThreadWaitCondition );
       if( mUpdateAheadOfRender <= 0 && ! mRenderThreadStop )
       {
-        LOG_UPDATE_COUNTER_RENDER( "updateAheadOfRender(%d) WAIT", mUpdateAheadOfRender );
-        mRenderThreadWaitCondition.Wait( renderLock );
+        do
+        {
+          LOG_UPDATE_COUNTER_RENDER( "updateAheadOfRender(%d) WAIT", mUpdateAheadOfRender );
+          mRenderThreadWaitCondition.Wait( renderLock );
+        } while( mUpdateAheadOfRender <= 0 && ! mRenderThreadStop && ! mRenderThreadReplacingSurface );
       }
       else
       {
@@ -576,6 +580,46 @@ bool ThreadSynchronization::VSyncReady( bool validSync, unsigned int frameNumber
   return IsVSyncThreadRunning(); // Call to this function locks so should not be called if we have a scoped-lock
 }
 
+/////////////////////////////////////////////////////////////////////////////////////////////////
+// POST RENDERING: EVENT THREAD
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+void ThreadSynchronization::PostRenderComplete()
+{
+  LOG_EVENT_TRACE;
+
+  {
+    ConditionalWait::ScopedLock lock( mRenderThreadWaitCondition );
+    mRenderThreadSurfaceRendered = TRUE;
+  }
+  mRenderThreadWaitCondition.Notify();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// POST RENDERING: RENDER THREAD
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void ThreadSynchronization::PostRenderStarted()
+{
+  LOG_RENDER_TRACE;
+
+  ConditionalWait::ScopedLock lock( mRenderThreadWaitCondition );
+  mRenderThreadSurfaceRendered = FALSE;
+}
+
+void ThreadSynchronization::PostRenderWaitForCompletion()
+{
+  LOG_RENDER_TRACE;
+
+  ConditionalWait::ScopedLock lock( mRenderThreadWaitCondition );
+  if( !mRenderThreadSurfaceRendered &&
+      !mRenderThreadReplacingSurface )
+  {
+    LOG_RENDER( "WAIT" );
+    mRenderThreadWaitCondition.Wait( lock );
+  }
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // ALL THREADS: Performance Marker
 ///////////////////////////////////////////////////////////////////////////////////////////////////
index 5f2ebfc..eea45c7 100644 (file)
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDES
 
 // INTERNAL INCLUDES
+#include <integration-api/thread-synchronization-interface.h>
 #include <base/interfaces/performance-interface.h>
 #include <base/conditional-wait.h>
 #include <trigger-event-interface.h>
@@ -47,7 +48,7 @@ class AdaptorInternalServices;
  * However the Core::Update() for frame N+2 may not be called, until the Core::Render() method for frame N has returned.
  *
  */
-class ThreadSynchronization
+class ThreadSynchronization : public Dali::ThreadSynchronizationInterface
 {
 public:
 
@@ -202,6 +203,33 @@ public:
   bool VSyncReady( bool validSync, unsigned int frameNumber, unsigned int seconds, unsigned int microseconds, unsigned int& numberOfVSyncsPerRender );
 
   /////////////////////////////////////////////////////////////////////////////////////////////////
+  // POST RENDERING
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  //// Called by the Event Thread if post-rendering is required
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @copydoc ThreadSynchronizationInterface::PostRenderComplete()
+   */
+  void PostRenderComplete();
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  //// Called by the Render Thread if post-rendering is required
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @copydoc ThreadSynchronizationInterface::PostRenderStarted()
+   */
+  void PostRenderStarted();
+
+  /**
+   * @copydoc ThreadSynchronizationInterface::PostRenderStarted()
+   */
+  void PostRenderWaitForCompletion();
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
   // Called by ALL Threads
   /////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -383,6 +411,8 @@ private:
   volatile unsigned int mRenderThreadStop;            ///< Whether the render-thread should be stopped (set by the update-thread, read by the render-thread).
   volatile unsigned int mRenderThreadReplacingSurface;///< Whether the render-thread should replace the surface (set by the event & render threads, read by the render-thread).
 
+  volatile unsigned int mRenderThreadSurfaceRendered; ///< Whether the render-surface has rendered our surface (set by the event & render threads, read by the render-thread).
+
   volatile unsigned int mEventThreadSurfaceReplaced;  ///< Checked by the event-thread & set by the render-thread when the surface has been replaced (set by the event & render threads, read by the event-thread).
 
   unsigned int mVSyncThreadInitialised;               ///< Whether the V-Sync thread has been initialised (only used by v-sync-thread).
index b23728d..2844105 100644 (file)
@@ -31,6 +31,7 @@ namespace Dali
 
 class EglInterface;
 class DisplayConnection;
+class ThreadSynchronizationInterface;
 
 namespace Integration
 {
@@ -149,6 +150,13 @@ public:
    */
   virtual void ReleaseLock() = 0;
 
+  /**
+   * @brief Sets the ThreadSynchronizationInterface
+   *
+   * @param threadSynchronization The thread-synchronization implementation.
+   */
+  virtual void SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization ) = 0;
+
 private:
 
   /**
index 9287572..2779d84 100644 (file)
@@ -1,6 +1,7 @@
 adaptor_integration_api_header_files = \
   $(adaptor_integration_api_dir)/adaptor.h \
   $(adaptor_integration_api_dir)/egl-interface.h \
+  $(adaptor_integration_api_dir)/thread-synchronization-interface.h \
   $(adaptor_integration_api_dir)/trigger-event-interface.h \
   $(adaptor_integration_api_dir)/trigger-event-factory-interface.h \
   $(adaptor_integration_api_dir)/trigger-event-factory.h \
diff --git a/adaptors/integration-api/thread-synchronization-interface.h b/adaptors/integration-api/thread-synchronization-interface.h
new file mode 100644 (file)
index 0000000..15164be
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef __DALI_INTEGRATION_THREAD_SYNCHRONIZATION_INTERFACE_H__
+#define __DALI_INTEGRATION_THREAD_SYNCHRONIZATION_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+namespace Dali
+{
+
+/**
+ * @brief Interface for the ThreadSyncrhonization handler.
+ *
+ * This handler ensure the threads are synchronized properly.
+ */
+class ThreadSynchronizationInterface
+{
+public:
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by the Event Thread if post-rendering is required
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Surface informs that the post-render has been completed.
+   *
+   * @note Should only be called by the Event Thread if post-rendering is required.
+   */
+  virtual void PostRenderComplete() = 0;
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by the Render Thread if post-rendering is required
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Called just before the post rendering is done by the surface.
+   *
+   * @note Should only be called by the Render Thread if post-rendering is required.
+   */
+  virtual void PostRenderStarted() = 0;
+
+  /**
+   * @brief Blocks the render thread until the post rendering has been completed by the surface.
+   *
+   * @note Should only be called by the Render Thread if post-rendering is required.
+   */
+  virtual void PostRenderWaitForCompletion() = 0;
+
+protected:
+
+  /**
+   * @brief Protected constructor, no creation through this interface
+   */
+  ThreadSynchronizationInterface( ) { }
+
+  /**
+   * Virtual protected destructor, no deletion through this interface
+   */
+  virtual ~ThreadSynchronizationInterface() { }
+
+private:
+
+  // Undefined copy constructor.
+  ThreadSynchronizationInterface( const ThreadSynchronizationInterface& );
+
+  // Undefined assignment operator.
+  ThreadSynchronizationInterface& operator=( const ThreadSynchronizationInterface& );
+};
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_THREAD_SYNCHRONIZATION_INTERFACE_H__
index ebe2532..190e1ae 100644 (file)
@@ -107,6 +107,11 @@ public: // from Dali::RenderSurface
    */
   virtual void StopRender();
 
+  /**
+   * @copydoc Dali::RenderSurface::SetThreadSynchronization
+   */
+  virtual void SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization );
+
 private:
   enum SyncMode
   {
index b90e324..471462f 100644 (file)
@@ -107,25 +107,12 @@ public: // from Dali::RenderSurface
    */
   virtual void StopRender();
 
-private:
-  enum SyncMode
-  {
-    SYNC_MODE_NONE,
-    SYNC_MODE_WAIT
-  };
-
   /**
-   * Set the sync mode.
-   * @param[in] syncMode The sync mode
+   * @copydoc Dali::RenderSurface::SetThreadSynchronization
    */
-  void SetSyncMode( SyncMode syncMode );
+  virtual void SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization );
 
-  /**
-   * If sync mode is WAIT, then acquire a lock. This prevents render thread from
-   * continuing until the pixmap has been drawn by the compositor.
-   * It must be released for rendering to continue.
-   */
-  void AcquireLock();
+private:
 
   /**
    * Release any locks.
index f104850..cc76c24 100644 (file)
@@ -140,6 +140,11 @@ void PixmapRenderSurface::StopRender()
   // FIXME
 }
 
+void PixmapRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
+{
+  // Nothing to do
+}
+
 void PixmapRenderSurface::CreateWlRenderable()
 {
   // check we're creating one with a valid size
index cd565c9..38a2d44 100644 (file)
@@ -228,6 +228,11 @@ void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
   mWlWindow = AnyCast< Ecore_Wl_Window* >( surfaceId );
 }
 
+void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& /* threadSynchronization */ )
+{
+  // Nothing to do.
+}
+
 void WindowRenderSurface::ReleaseLock()
 {
   // Nothing to do.
index 9a27b8b..7aea88b 100644 (file)
@@ -134,6 +134,11 @@ public: // from Dali::RenderSurface
   virtual void StopRender();
 
   /**
+   * @copydoc Dali::RenderSurface::SetThreadSynchronization
+   */
+  virtual void SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization );
+
+  /**
    * @copydoc Dali::RenderSurface::ReleaseLock()
    */
   virtual void ReleaseLock();
index fa26edb..7f32b6e 100644 (file)
 
 // INTERNAL INCLUDES
 
+#include <integration-api/thread-synchronization-interface.h>
 #include <ecore-x-types.h>
 #include <trigger-event.h>
 #include <gl/egl-implementation.h>
 #include <base/display-connection.h>
 #include <base/conditional-wait.h>
 
-
 namespace Dali
 {
 
@@ -49,14 +49,10 @@ extern Debug::Filter* gRenderSurfaceLogFilter;
 namespace ECore
 {
 
-
 struct PixmapRenderSurface::Impl
 {
-  Internal::Adaptor::ConditionalWait  mSyncNotify;   ///< condition to notify main thread that pixmap was flushed to onscreen
-  Dali::Mutex                         mSyncMutex;    ///< mutex to lock during waiting sync
-  Ecore_X_Pixmap                      mX11Pixmap;    ///< X-Pixmap
-  SyncMode                            mSyncMode;     ///< Stores whether the post render should block waiting for compositor
-  bool                                mSyncReceived; ///< true, when a pixmap sync has occurred, (cleared after reading)
+  Ecore_X_Pixmap                  mX11Pixmap;             ///< X-Pixmap
+  ThreadSynchronizationInterface* mThreadSynchronization; ///< A pointer to the thread-synchronization
 };
 
 PixmapRenderSurface::PixmapRenderSurface(Dali::PositionSize positionSize,
@@ -66,8 +62,7 @@ PixmapRenderSurface::PixmapRenderSurface(Dali::PositionSize positionSize,
 : EcoreXRenderSurface( positionSize, surface, name, isTransparent ),
   mImpl( new Impl )
 {
-  mImpl->mSyncMode = SYNC_MODE_NONE;
-  mImpl->mSyncReceived = false;
+  mImpl->mThreadSynchronization = NULL;
   Init( surface );
 }
 
@@ -138,7 +133,6 @@ bool PixmapRenderSurface::ReplaceEGLSurface( EglInterface& egl )
 
 void PixmapRenderSurface::StartRender()
 {
-
 }
 
 bool PixmapRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
@@ -152,7 +146,10 @@ void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstract
   // flush gl instruction queue
   glAbstraction.Flush();
 
-  mImpl->mSyncReceived = false;
+  if( mImpl->mThreadSynchronization )
+  {
+    mImpl->mThreadSynchronization->PostRenderStarted();
+  }
 
   // create damage for client applications which wish to know the update timing
   if( mRenderNotification )
@@ -188,18 +185,22 @@ void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstract
     }
   }
 
-  if( !replacingSurface && mImpl->mSyncMode != SYNC_MODE_NONE )
+  if( mImpl->mThreadSynchronization )
   {
-    AcquireLock();
+    mImpl->mThreadSynchronization->PostRenderWaitForCompletion();
   }
 }
 
 void PixmapRenderSurface::StopRender()
 {
-  SetSyncMode(SYNC_MODE_NONE);
   ReleaseLock();
 }
 
+void PixmapRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
+{
+  mImpl->mThreadSynchronization = &threadSynchronization;
+}
+
 void PixmapRenderSurface::CreateXRenderable()
 {
   // check we're creating one with a valid size
@@ -233,26 +234,12 @@ void PixmapRenderSurface::UseExistingRenderable( unsigned int surfaceId )
   mImpl->mX11Pixmap = static_cast< Ecore_X_Pixmap >( surfaceId );
 }
 
-void PixmapRenderSurface::SetSyncMode( SyncMode syncMode )
-{
-  mImpl->mSyncMode = syncMode;
-}
-
-void PixmapRenderSurface::AcquireLock()
+void PixmapRenderSurface::ReleaseLock()
 {
-  if( !mImpl->mSyncReceived )
+  if( mImpl->mThreadSynchronization )
   {
-    mImpl->mSyncNotify.Wait();
+    mImpl->mThreadSynchronization->PostRenderComplete();
   }
-  mImpl->mSyncReceived = false;
-}
-
-void PixmapRenderSurface::ReleaseLock()
-{
-  mImpl->mSyncReceived = true;
-
-  // wake render thread if it was waiting for the notify
-  mImpl->mSyncNotify.Notify();
 }
 
 } // namespace ECore
index 18b8d14..0580f54 100644 (file)
@@ -297,6 +297,11 @@ void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
   mX11Window = static_cast< Ecore_X_Window >( surfaceId );
 }
 
+void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& /* threadSynchronization */ )
+{
+  // Nothing to do.
+}
+
 void WindowRenderSurface::ReleaseLock()
 {
   // Nothing to do.
index 77b5e0a..f9b5b41 100644 (file)
@@ -135,6 +135,11 @@ public: // from Dali::RenderSurface
   virtual void StopRender();
 
   /**
+   * @copydoc Dali::RenderSurface::SetThreadSynchronization
+   */
+  virtual void SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization );
+
+  /**
    * @copydoc Dali::RenderSurface::ReleaseLock()
    */
   virtual void ReleaseLock();