Move pixmap synchronization from RenderThread to PixmapRenderSurface. 34/17934/8
authorJavon Prince <javon.prince@samsung.com>
Wed, 12 Mar 2014 13:47:49 +0000 (13:47 +0000)
committerJavon Prince <javon.prince@samsung.com>
Thu, 20 Mar 2014 14:59:16 +0000 (14:59 +0000)
Change-Id: I36637b0e289cc74d61d11da050861da99413935a
Signed-off-by: Javon Prince <javon.prince@samsung.com>
adaptors/base/render-thread.cpp
adaptors/base/render-thread.h
adaptors/tizen/internal/common/ecore-x/ecore-x-render-surface.cpp
adaptors/tizen/internal/common/ecore-x/ecore-x-render-surface.h
adaptors/tizen/internal/common/ecore-x/native-buffer-render-surface.cpp
adaptors/tizen/internal/common/ecore-x/native-buffer-render-surface.h
adaptors/tizen/internal/common/ecore-x/pixmap-render-surface.cpp
adaptors/tizen/internal/common/ecore-x/pixmap-render-surface.h
adaptors/tizen/internal/common/ecore-x/window-render-surface.cpp
adaptors/tizen/internal/common/ecore-x/window-render-surface.h
adaptors/tizen/internal/common/render-surface-impl.h

index 1b3ba39..387f4ad 100644 (file)
@@ -50,24 +50,13 @@ RenderThread::RenderThread( UpdateRenderSynchronization& sync,
   mEglFactory( &adaptorInterfaces.GetEGLFactoryInterface()),
   mEGL( NULL ),
   mThread( NULL ),
-  mUsingPixmap( false ),
   mSurfaceReplacing( false ),
   mNewDataAvailable( false ),
-  mPixmapSyncReceived( false ),
-  mPixmapSyncRunning( false ),
-  mCurrentMicroSec(0),
   mSurfaceReplaceCompleted( false ),
   mLogOptions( logOptions )
 {
   // set the initial values before render thread starts
   mCurrent.surface = adaptorInterfaces.GetRenderSurfaceInterface();
-
-  // set the pixmap flag, if we're using one
-  if( (mCurrent.surface->GetType() == Dali::RenderSurface::PIXMAP ) ||
-      (mCurrent.surface->GetType() == Dali::RenderSurface::NATIVE_BUFFER ) )
-  {
-    mUsingPixmap = true;
-  }
 }
 
 RenderThread::~RenderThread()
@@ -87,12 +76,8 @@ void RenderThread::Start()
   // create the render thread, initially we are rendering
   mThread = new boost::thread(boost::bind(&RenderThread::Run, this));
 
-  // Inform render thread to block waiting for PixmapSync
-  if( mUsingPixmap )
-  {
-    boost::unique_lock< boost::mutex > lock( mPixmapSyncMutex );
-    mPixmapSyncRunning = true;
-  }
+  // Inform surface to block waiting for RenderSync
+  mCurrent.surface->SetSyncMode( RenderSurface::SYNC_MODE_WAIT );
  }
 
 void RenderThread::Stop()
@@ -100,18 +85,9 @@ void RenderThread::Stop()
   // shutdown the render thread and destroy the opengl context
   if( mThread )
   {
-    // Inform render thread not to block waiting for PixmapSync
-    if( mUsingPixmap )
-    {
-      boost::unique_lock< boost::mutex > lock( mPixmapSyncMutex );
-      mPixmapSyncRunning = false;
-    }
-
+    // Tell surface we have stopped rendering
     mCurrent.surface->StopRender();
 
-    // need to simulate a RenderSync to get render-thread to finish
-    RenderSync();
-
     // wait for the thread to finish
     mThread->join();
 
@@ -167,17 +143,7 @@ void RenderThread::SetVSyncMode( EglInterface::SyncMode syncMode )
 
 void RenderThread::RenderSync()
 {
-  if( !mUsingPixmap )
-  {
-    return;
-  }
-  {
-    boost::unique_lock< boost::mutex > lock( mPixmapSyncMutex );
-    mPixmapSyncReceived = true;
-  }
-
-  // awake render thread if it was waiting for the notify
-  mPixmapSyncNotify.notify_all();
+  mCurrent.surface->RenderSync();
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -269,11 +235,8 @@ void RenderThread::InitializeEgl()
   // Make it current
   mEGL->MakeContextCurrent();
 
-  if( !mUsingPixmap )
-  {
-    // set the initial sync mode
-    mEGL->SetRefreshSync( mCurrent.syncMode );
-  }
+  // set the initial sync mode
+  mEGL->SetRefreshSync( mCurrent.syncMode );
 
   // tell core it has a context
   mCore.ContextCreated();
@@ -378,21 +341,8 @@ bool RenderThread::PreRender()
 
 void RenderThread::PostRender( unsigned int timeDelta )
 {
-  const bool waitForSync = mCurrent.surface->PostRender( *mEGL, mGLES, timeDelta );
-
-  if( waitForSync )
-  {
-    boost::unique_lock< boost::mutex > lock( mPixmapSyncMutex );
-
-    // wait until synced,
-    // this blocks the thread here and releases the mPixmapSyncMutex (so the main thread can use it)
-    // if surface is replacing, forcely update without pixmap sync
-    if( mPixmapSyncRunning && !mPixmapSyncReceived && !mSurfaceReplacing )
-    {
-      mPixmapSyncNotify.wait( lock );
-    }
-    mPixmapSyncReceived = false;
-  }
+  mCurrent.surface->PostRender( *mEGL, mGLES, timeDelta,
+                                mSurfaceReplacing ? RenderSurface::SYNC_MODE_NONE : RenderSurface::SYNC_MODE_WAIT );
 }
 
 } // namespace Adaptor
index eb4fa89..3330ffa 100644 (file)
@@ -228,13 +228,6 @@ private: // Data
     volatile int* mFlag;
   };
 
-  // sync for waiting offscreen flushed to onscreen
-  boost::mutex              mPixmapSyncMutex;      ///< mutex to lock during waiting sync
-  boost::condition_variable mPixmapSyncNotify;     ///< condition to notify main thread that pixmap was flushed to onscreen
-  bool                      mPixmapSyncReceived;   ///< true, when a pixmap sync has occurred, (cleared after reading)
-  bool                      mPixmapSyncRunning;    ///< true, while render thread is running and needs to wait for pixmap syncs
-  unsigned long             mCurrentMicroSec;
-
   // sync for waiting for surface change
   boost::mutex              mSurfaceChangedMutex;  ///< mutex to lock during surface replacing
   boost::condition_variable mSurfaceChangedNotify; ///< condition to notify main thread that surface has been changed
index 2a33569..c78e1d0 100644 (file)
@@ -67,12 +67,13 @@ RenderSurface::RenderSurface( SurfaceType type,
 : mMainDisplay(NULL),
   mType(type),
   mPosition(positionSize),
-  mOwnSurface(false),
-  mOwnDisplay(false),
   mTitle(name),
   mColorDepth(isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24),
   mRenderMode((type == PIXMAP) ? RENDER_SYNC : RENDER_DEFAULT),
   mRenderNotification( NULL ),
+  mSyncReceived( false ),
+  mOwnSurface(false),
+  mOwnDisplay(false),
   mIsStopped( false )
 {
   // see if there is a display in boost::any display
@@ -239,6 +240,16 @@ void RenderSurface::ConsumeEvents()
   }
 }
 
+void RenderSurface::StopRender()
+{
+  // Stop blocking waiting for sync
+  SetSyncMode( RenderSurface::SYNC_MODE_NONE );
+  // Simulate a RenderSync in case render-thread is currently blocked
+  RenderSync();
+
+  mIsStopped = true;
+}
+
 void RenderSurface::SetDisplay( boost::any display )
 {
   // the render surface can be passed either EFL e-core types, or x11 types
@@ -296,9 +307,29 @@ unsigned int RenderSurface::GetSurfaceId( boost::any surface ) const
   return surfaceId;
 }
 
-bool RenderSurface::RenderSync( unsigned int timeDelta )
+void RenderSurface::RenderSync()
 {
-  if( mRenderMode > Dali::RenderSurface::RENDER_SYNC )
+  // nothing to do
+}
+
+void RenderSurface::DoRenderSync( unsigned int timeDelta, SyncMode syncMode )
+{
+  // Should block waiting for RenderSync?
+  if( mRenderMode == Dali::RenderSurface::RENDER_SYNC )
+  {
+    boost::unique_lock< boost::mutex > lock( mSyncMutex );
+
+    // wait for sync
+    if( syncMode != SYNC_MODE_NONE &&
+        mSyncMode != SYNC_MODE_NONE &&
+        !mSyncReceived )
+    {
+      mSyncNotify.wait( lock );
+    }
+    mSyncReceived = false;
+  }
+  // Software sync based on a timed delay?
+  else if( mRenderMode > Dali::RenderSurface::RENDER_SYNC )
   {
     unsigned int syncPeriod( MICROSECONDS_PER_SECOND / static_cast< unsigned int >( mRenderMode ) - MILLISECONDS_PER_SECOND );
     if( timeDelta < syncPeriod )
@@ -306,8 +337,6 @@ bool RenderSurface::RenderSync( unsigned int timeDelta )
       usleep( syncPeriod - timeDelta );
     }
   }
-
-  return mRenderMode == Dali::RenderSurface::RENDER_SYNC;
 }
 
 } // namespace ECoreX
index 5a60b86..49fd189 100644 (file)
@@ -19,7 +19,7 @@
 
 // EXTERNAL INCLUDES
 #include <string>
-
+#include <boost/thread.hpp>
 #include <Ecore_X.h>
 #include <dali/public-api/common/dali-common.h>
 
@@ -177,6 +177,11 @@ public:  // from Internal::Adaptor::RenderSurface
   virtual void ConsumeEvents();
 
   /**
+   * @copydoc Dali::Internal::Adaptor::RenderSurface::RenderSync()
+   */
+  virtual void RenderSync();
+
+  /**
    * @copydoc Dali::Internal::Adaptor::RenderSurface::PreRender()
    */
   virtual bool PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction ) = 0;
@@ -184,12 +189,17 @@ public:  // from Internal::Adaptor::RenderSurface
   /**
    * @copydoc Dali::Internal::Adaptor::RenderSurface::PostRender()
    */
-  virtual bool PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta ) = 0;
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta, SyncMode syncMode ) = 0;
 
   /**
    * @copydoc Dali::Internal::Adaptor::RenderSurface::StopRender()
    */
-  virtual void StopRender() { mIsStopped = true;};
+  virtual void StopRender();
+
+  /**
+   * @copydoc Dali::Internal::Adaptor::RenderSurface::SetSyncMode()
+   */
+  virtual void SetSyncMode( SyncMode syncMode ) { mSyncMode = syncMode; }
 
 private:
 
@@ -222,9 +232,9 @@ protected:
   /**
    * Perform render sync
    * @param[in] currentTime Current time in microseconds
-   * @return true if the calling thread should wait for a RenderSync from Adaptor
+   * @param[in] syncMode Wait for RenderSync (from Adaptor) flag. A member of SyncMode
    */
-  bool RenderSync( unsigned int timeDelta );
+  void DoRenderSync( unsigned int timeDelta, SyncMode syncMode );
 
 protected: // Data
 
@@ -232,14 +242,17 @@ protected: // Data
   Ecore_X_Window              mRootWindow;         ///< X-Root window
   SurfaceType                 mType;               ///< type of renderable
   PositionSize                mPosition;           ///< Position
-  bool                        mOwnSurface;         ///< Whether we own the surface (responsible for deleting it)
-  bool                        mOwnDisplay;         ///< Whether we own the display (responsible for deleting it)
   std::string                 mTitle;              ///< Title of window which shows from "xinfo -topvwins" command
   ColorDepth                  mColorDepth;         ///< Color depth of surface (32 bit or 24 bit)
   RenderMode                  mRenderMode;         ///< Render mode for pixmap surface type
   TriggerEvent*               mRenderNotification; ///< Render notificatin trigger
+  boost::mutex                mSyncMutex;          ///< mutex to lock during waiting sync
+  boost::condition_variable   mSyncNotify;         ///< condition to notify main thread that pixmap was flushed to onscreen
+  SyncMode                    mSyncMode;
+  bool                        mSyncReceived;       ///< true, when a pixmap sync has occurred, (cleared after reading)
+  bool                        mOwnSurface;         ///< Whether we own the surface (responsible for deleting it)
+  bool                        mOwnDisplay;         ///< Whether we own the display (responsible for deleting it)
   bool                        mIsStopped;          ///< Render should be stopped
-
 };
 
 } // namespace ECoreX
index e7372d7..5e8c9cb 100644 (file)
@@ -178,7 +178,7 @@ bool NativeBufferRenderSurface::PreRender( EglInterface& egl, Integration::GlAbs
   return !mIsStopped; // fail if it is stopped
 }
 
-bool NativeBufferRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta )
+void NativeBufferRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta, SyncMode syncMode )
 {
   glAbstraction.Flush();
 
@@ -197,7 +197,7 @@ bool NativeBufferRenderSurface::PostRender( EglInterface& egl, Integration::GlAb
   }
 
   // Do render synchronisation
-  return RenderSync( timeDelta );
+  DoRenderSync( timeDelta, syncMode );
 }
 
 void NativeBufferRenderSurface::CreateXRenderable()
index f64a535..b12387b 100644 (file)
@@ -99,7 +99,7 @@ public: // from Internal::Adaptor::RenderSurface
   virtual bool PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction );
 
   /// @copydoc Dali::RenderSurface::PostRender
-  virtual bool PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta );
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta, SyncMode syncMode );
 
 protected:
 
index ea66229..a51365e 100644 (file)
@@ -134,7 +134,7 @@ bool PixmapRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction&
   return true;
 }
 
-bool PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta )
+void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta, SyncMode syncMode )
 {
   // flush gl instruction queue
   glAbstraction.Flush();
@@ -173,7 +173,7 @@ bool PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstract
   }
 
   // Do render synchronisation
-  return RenderSync( timeDelta );
+  DoRenderSync( timeDelta, syncMode );
 }
 
 void PixmapRenderSurface::CreateXRenderable()
@@ -206,6 +206,17 @@ void PixmapRenderSurface::UseExistingRenderable( unsigned int surfaceId )
   mX11Pixmap = static_cast< Ecore_X_Pixmap >( surfaceId );
 }
 
+void PixmapRenderSurface::RenderSync()
+{
+  {
+    boost::unique_lock< boost::mutex > lock( mSyncMutex );
+    mSyncReceived = true;
+  }
+
+  // wake render thread if it was waiting for the notify
+  mSyncNotify.notify_all();
+}
+
 } // namespace ECoreX
 
 } // namespace Adaptor
index d81a08f..c3742cb 100644 (file)
@@ -101,6 +101,11 @@ public: // from Internal::Adaptor::RenderSurface
   virtual bool ReplaceEGLSurface( EglInterface& egl );
 
   /**
+   * @copydoc Dali::Internal::Adaptor::RenderSurface::RenderSync()
+   */
+  virtual void RenderSync();
+
+  /**
    * @copydoc Dali::Internal::Adaptor::RenderSurface::PreRender()
    */
   virtual bool PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction );
@@ -108,7 +113,7 @@ public: // from Internal::Adaptor::RenderSurface
   /**
    * @copydoc Dali::Internal::Adaptor::RenderSurface::PostRender()
    */
-  virtual bool PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta );
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta, SyncMode syncMode );
 
 private:
 
index 916cbf1..cadb610 100644 (file)
@@ -193,7 +193,7 @@ bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction&
   return true;
 }
 
-bool WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta )
+void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int, SyncMode )
 {
   EglImplementation& eglImpl = static_cast<EglImplementation&>( egl );
   eglImpl.SwapBuffers();
@@ -215,9 +215,6 @@ bool WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstract
 
     mNeedToApproveDeiconify = false;
   }
-
-  // Does not need render thread to wait for sync
-  return false;
 }
 
 void WindowRenderSurface::CreateXRenderable()
index d31dd09..373bf2a 100644 (file)
@@ -129,7 +129,7 @@ public:  // from Internal::Adaptor::RenderSurface
   /**
    * @copydoc Dali::Internal::Adaptor::RenderSurface::PostRender()
    */
-  virtual bool PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta );
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta, SyncMode syncMode );
 
 protected:
 
index c1e818f..0edc227 100644 (file)
@@ -46,6 +46,14 @@ class DALI_IMPORT_API RenderSurface : public Dali::RenderSurface
 {
 public:
 
+  enum SyncMode
+  {
+    SYNC_MODE_NONE,               ///< Do not wait for RenderSync
+    SYNC_MODE_WAIT                ///< Wait for RenderSync
+  };
+
+public:
+
   /**
    * Constructor
    */
@@ -113,6 +121,11 @@ public: // API
   virtual void ConsumeEvents() = 0;
 
   /**
+   * Called after offscreen is posted to onscreen
+   */
+  virtual void RenderSync() = 0;
+
+  /**
    * Invoked by render thread before Core::Render
    * @param[in] egl The Egl interface
    * @param[in] glAbstraction OpenGLES abstraction interface
@@ -125,14 +138,21 @@ public: // API
    * @param[in] egl The Egl interface
    * @param[in] glAbstraction OpenGLES abstraction interface
    * @param[in] deltaTime Time (in microseconds) since PostRender was last called.
-   * @return true if a vsync is required, otherwise false
+   * @param[in] syncMode Wait for render sync flag.
+   *                     RenderSync will be skipped if this or SetSyncMode() is set to SYNC_MODE_NONE.
    */
-  virtual bool PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int deltaTime ) = 0;
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int deltaTime, SyncMode syncMode ) = 0;
 
   /**
    * Invoked by render thread when the thread should be stop
    */
   virtual void StopRender() = 0;
+
+  /**
+   * Set whether the surface should wait for RenderSync notifications
+   * @param[in] syncMode Wait for render sync flag. A member of SyncMode
+   */
+  virtual void SetSyncMode( SyncMode syncMode ) = 0;
 };
 
 } // namespace Adaptor