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()
// 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()
// 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();
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();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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();
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
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
: 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
}
}
+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
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 )
usleep( syncPeriod - timeDelta );
}
}
-
- return mRenderMode == Dali::RenderSurface::RENDER_SYNC;
}
} // namespace ECoreX
// EXTERNAL INCLUDES
#include <string>
-
+#include <boost/thread.hpp>
#include <Ecore_X.h>
#include <dali/public-api/common/dali-common.h>
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;
/**
* @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:
/**
* 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
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
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();
}
// Do render synchronisation
- return RenderSync( timeDelta );
+ DoRenderSync( timeDelta, syncMode );
}
void NativeBufferRenderSurface::CreateXRenderable()
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:
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();
}
// Do render synchronisation
- return RenderSync( timeDelta );
+ DoRenderSync( timeDelta, syncMode );
}
void PixmapRenderSurface::CreateXRenderable()
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
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 );
/**
* @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:
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();
mNeedToApproveDeiconify = false;
}
-
- // Does not need render thread to wait for sync
- return false;
}
void WindowRenderSurface::CreateXRenderable()
/**
* @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:
{
public:
+ enum SyncMode
+ {
+ SYNC_MODE_NONE, ///< Do not wait for RenderSync
+ SYNC_MODE_WAIT ///< Wait for RenderSync
+ };
+
+public:
+
/**
* Constructor
*/
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
* @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