#include <dali/integration-api/gl-abstraction.h>
#include <dali/integration-api/debug.h>
+#include <dali/devel-api/threading/mutex.h>
+#include <dali/devel-api/threading/conditional-wait.h>
// 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>
namespace Dali
{
-namespace Internal
-{
-
-namespace Adaptor
-{
-
#if defined(DEBUG_ENABLED)
extern Debug::Filter* gRenderSurfaceLogFilter;
#endif
namespace ECore
{
-PixmapRenderSurface::PixmapRenderSurface( Dali::PositionSize positionSize,
- Any surface,
- Any display,
- const std::string& name,
- bool isTransparent)
-: RenderSurface( Dali::RenderSurface::PIXMAP, positionSize, surface, display, name, isTransparent )
+namespace
+{
+static const int INITIAL_PRODUCE_BUFFER_INDEX = 0;
+static const int INITIAL_CONSUME_BUFFER_INDEX = 1;
+static const int BUFFER_COUNT = 2;
+}
+
+struct PixmapRenderSurface::Impl
+{
+ Impl()
+ : mProduceBufferIndex( INITIAL_PRODUCE_BUFFER_INDEX ),
+ mConsumeBufferIndex( INITIAL_CONSUME_BUFFER_INDEX ),
+ mThreadSynchronization(NULL)
+ {
+ for (int i = 0; i != BUFFER_COUNT; ++i)
+ {
+ mX11Pixmaps[i] = 0;
+ mEglSurfaces[i] = 0;
+ }
+ }
+
+ int mProduceBufferIndex;
+ int mConsumeBufferIndex;
+ XPixmap mX11Pixmaps[BUFFER_COUNT]; ///< X-Pixmap
+ EGLSurface mEglSurfaces[BUFFER_COUNT];
+ ThreadSynchronizationInterface* mThreadSynchronization; ///< A pointer to the thread-synchronization
+ ConditionalWait mPixmapCondition; ///< condition to share pixmap
+};
+
+PixmapRenderSurface::PixmapRenderSurface(Dali::PositionSize positionSize,
+ Any surface,
+ const std::string& name,
+ bool isTransparent)
+: EcoreXRenderSurface( positionSize, surface, name, isTransparent ),
+ mImpl( new Impl )
{
Init( surface );
}
// release the surface if we own one
if( mOwnSurface )
{
- // if we did create the pixmap, delete the pixmap
- DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::General, "Own pixmap (%x) freed\n", mX11Pixmap );
- ecore_x_pixmap_free( mX11Pixmap );
+ for (int i = 0; i < BUFFER_COUNT; ++i)
+ {
+ Ecore_X_Pixmap pixmap = mImpl->mX11Pixmaps[i];
+
+ // if we did create the pixmap, delete the pixmap
+ DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::General, "Own pixmap (%x) freed\n", pixmap );
+ ecore_x_pixmap_free( pixmap );
+ }
}
+
+ delete mImpl;
}
Ecore_X_Drawable PixmapRenderSurface::GetDrawable()
{
- return (Ecore_X_Drawable)mX11Pixmap;
-}
+ Ecore_X_Pixmap pixmap = 0;
+ {
+ ConditionalWait::ScopedLock lock( mImpl->mPixmapCondition );
+ pixmap = mImpl->mX11Pixmaps[mImpl->mConsumeBufferIndex];
+ }
-Dali::RenderSurface::SurfaceType PixmapRenderSurface::GetType()
-{
- return Dali::RenderSurface::PIXMAP;
+ return Ecore_X_Drawable( pixmap );
}
Any PixmapRenderSurface::GetSurface()
{
- return Any( mX11Pixmap );
+ Ecore_X_Pixmap pixmap = 0;
+ {
+ ConditionalWait::ScopedLock lock( mImpl->mPixmapCondition );
+ pixmap = mImpl->mX11Pixmaps[mImpl->mProduceBufferIndex];
+ }
+
+ return Any( pixmap );
}
-void PixmapRenderSurface::InitializeEgl( EglInterface& eglIf )
+void PixmapRenderSurface::InitializeEgl( EglInterface& egl )
{
DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
- EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
- eglImpl.InitializeGles( reinterpret_cast< EGLNativeDisplayType >( mMainDisplay ) );
+ Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
eglImpl.ChooseConfig(false, mColorDepth);
}
-void PixmapRenderSurface::CreateEglSurface( EglInterface& eglIf )
+void PixmapRenderSurface::CreateEglSurface( EglInterface& egl )
{
DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
- EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
+ Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
- // create the EGL surface
- // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
- XPixmap pixmap = static_cast< XPixmap>( mX11Pixmap );
- eglImpl.CreateSurfacePixmap( (EGLNativePixmapType)pixmap, mColorDepth ); // reinterpret_cast does not compile
+ for (int i = 0; i < BUFFER_COUNT; ++i)
+ {
+ // create the EGL surface
+ // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
+ XPixmap pixmap = static_cast<XPixmap>( mImpl->mX11Pixmaps[i] );
+ mImpl->mEglSurfaces[i] = eglImpl.CreateSurfacePixmap( EGLNativePixmapType( pixmap ), mColorDepth ); // reinterpret_cast does not compile
+ }
}
-void PixmapRenderSurface::DestroyEglSurface( EglInterface& eglIf )
+void PixmapRenderSurface::DestroyEglSurface( EglInterface& egl )
{
DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
- EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
- eglImpl.DestroySurface();
+ Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
+
+ for (int i = 0; i < BUFFER_COUNT; ++i)
+ {
+ // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
+ XPixmap pixmap = static_cast<XPixmap>( mImpl->mX11Pixmaps[i] );
+ eglImpl.MakeCurrent( EGLNativePixmapType( pixmap ), mImpl->mEglSurfaces[i] );
+ eglImpl.DestroySurface();
+ }
}
-bool PixmapRenderSurface::ReplaceEGLSurface( EglInterface& eglIf )
+bool PixmapRenderSurface::ReplaceEGLSurface( EglInterface& egl )
{
DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
- EglImplementation& eglImpl = static_cast<EglImplementation&>( eglIf );
- eglImpl.InitializeGles( reinterpret_cast< EGLNativeDisplayType >( mMainDisplay ) );
+ bool contextLost = false;
+
+ Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
+
+ for (int i = 0; i < BUFFER_COUNT; ++i)
+ {
+ // a new surface for the new pixmap
+ // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
+ XPixmap pixmap = static_cast<XPixmap>( mImpl->mX11Pixmaps[i] );
+ contextLost = eglImpl.ReplaceSurfacePixmap( EGLNativePixmapType( pixmap ), mImpl->mEglSurfaces[i] ); // reinterpret_cast does not compile
+ }
- // a new surface for the new pixmap
// need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
- XPixmap pixmap = static_cast< XPixmap>( mX11Pixmap );
- return eglImpl.ReplaceSurfacePixmap( (EGLNativePixmapType)pixmap, // reinterpret_cast does not compile
- reinterpret_cast< EGLNativeDisplayType >( mMainDisplay ) );
+ XPixmap pixmap = static_cast<XPixmap>( mImpl->mX11Pixmaps[mImpl->mProduceBufferIndex] );
+ eglImpl.MakeCurrent( EGLNativePixmapType( pixmap ), mImpl->mEglSurfaces[mImpl->mProduceBufferIndex] );
+
+ return contextLost;
}
-bool PixmapRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& )
+void PixmapRenderSurface::StartRender()
{
- // nothing to do for pixmaps
+}
+
+bool PixmapRenderSurface::PreRender( EglInterface& egl, Integration::GlAbstraction& )
+{
+ // Nothing to do for pixmaps
return true;
}
-void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, unsigned int timeDelta, SyncMode syncMode )
+void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
{
// flush gl instruction queue
glAbstraction.Flush();
+ if( mImpl->mThreadSynchronization )
+ {
+ mImpl->mThreadSynchronization->PostRenderStarted();
+ }
+
+ {
+ ConditionalWait::ScopedLock lock( mImpl->mPixmapCondition );
+ mImpl->mConsumeBufferIndex = __sync_fetch_and_xor( &mImpl->mProduceBufferIndex, 1 ); // Swap buffer indexes.
+
+ Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
+
+ // need to cast to X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
+ XPixmap pixmap = static_cast<XPixmap>( mImpl->mX11Pixmaps[mImpl->mProduceBufferIndex] );
+ eglImpl.MakeCurrent( EGLNativePixmapType( pixmap ), mImpl->mEglSurfaces[mImpl->mProduceBufferIndex] );
+ }
+
// create damage for client applications which wish to know the update timing
if( mRenderNotification )
{
}
else
{
- // as a fallback, send damage event. This is needed until livebox is fixed to
- // stop using damage events for render
- Ecore_X_Drawable drawable = GetDrawable();
+ // as a fallback, send damage event.
+ Ecore_X_Drawable drawable = Ecore_X_Drawable( mImpl->mX11Pixmaps[mImpl->mProduceBufferIndex] );
if( drawable )
{
rect.width = mPosition.width;
rect.height = mPosition.height;
+ XDisplay* display = AnyCast<XDisplay*>(displayConnection->GetDisplay());
+
// make a fixes region as updated area
- region = XFixesCreateRegion( mMainDisplay, &rect, 1 );
+ region = XFixesCreateRegion( display, &rect, 1 );
// add damage event to updated drawable
- XDamageAdd( mMainDisplay, (Drawable)drawable, region );
- XFixesDestroyRegion( mMainDisplay, region );
+ XDamageAdd( display, (Drawable)drawable, region );
+ XFixesDestroyRegion( display, region );
- XFlush( mMainDisplay );
+ XFlush( display );
}
}
- // Do render synchronisation
- DoRenderSync( timeDelta, syncMode );
+ if( mImpl->mThreadSynchronization )
+ {
+ mImpl->mThreadSynchronization->PostRenderWaitForCompletion();
+ }
+}
+
+void PixmapRenderSurface::StopRender()
+{
+ ReleaseLock();
+}
+
+void PixmapRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
+{
+ mImpl->mThreadSynchronization = &threadSynchronization;
}
void PixmapRenderSurface::CreateXRenderable()
// check we're creating one with a valid size
DALI_ASSERT_ALWAYS( mPosition.width > 0 && mPosition.height > 0 && "Pixmap size is invalid" );
- // create the pixmap
- mX11Pixmap = ecore_x_pixmap_new(0, mPosition.width, mPosition.height, mColorDepth);
+ for (int i = 0; i < BUFFER_COUNT; ++i)
+ {
+ // create the pixmap
+ mImpl->mX11Pixmaps[i] = ecore_x_pixmap_new(0, mPosition.width, mPosition.height, mColorDepth);
+
+ // clear the pixmap
+ unsigned int foreground;
+ Ecore_X_GC gc;
+ foreground = 0;
+ gc = ecore_x_gc_new( mImpl->mX11Pixmaps[i],
+ ECORE_X_GC_VALUE_MASK_FOREGROUND,
+ &foreground );
- // clear the pixmap
- unsigned int foreground;
- Ecore_X_GC gc;
- foreground = 0;
- gc = ecore_x_gc_new( mX11Pixmap,
- ECORE_X_GC_VALUE_MASK_FOREGROUND,
- &foreground );
- ecore_x_drawable_rectangle_fill( mX11Pixmap, gc, 0, 0, mPosition.width, mPosition.height );
+ DALI_ASSERT_ALWAYS( gc && "CreateXRenderable(): failed to get gc" );
- DALI_ASSERT_ALWAYS( mX11Pixmap && "Failed to create X pixmap" );
+ ecore_x_drawable_rectangle_fill( mImpl->mX11Pixmaps[i], gc, 0, 0, mPosition.width, mPosition.height );
- // we SHOULD guarantee the xpixmap/x11 window was created in x server.
- ecore_x_sync();
+ DALI_ASSERT_ALWAYS( mImpl->mX11Pixmaps[i] && "Failed to create X pixmap" );
- ecore_x_gc_free(gc);
+ // we SHOULD guarantee the xpixmap/x11 window was created in x server.
+ ecore_x_sync();
+
+ ecore_x_gc_free(gc);
+ }
}
void PixmapRenderSurface::UseExistingRenderable( unsigned int surfaceId )
{
- mX11Pixmap = static_cast< Ecore_X_Pixmap >( surfaceId );
}
-void PixmapRenderSurface::RenderSync()
+void PixmapRenderSurface::ReleaseLock()
{
+ if( mImpl->mThreadSynchronization )
{
- boost::unique_lock< boost::mutex > lock( mSyncMutex );
- mSyncReceived = true;
+ mImpl->mThreadSynchronization->PostRenderComplete();
}
+}
- // wake render thread if it was waiting for the notify
- mSyncNotify.notify_all();
+RenderSurface::Type PixmapRenderSurface::GetSurfaceType()
+{
+ return RenderSurface::ECORE_RENDER_SURFACE;
}
} // namespace ECore
-} // namespace Adaptor
-
-} // namespace Internal
-
} // namespace Dali