X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=adaptors%2Fx11%2Fpixmap-render-surface-x.cpp;h=a5cf8db353384410c813635910d60d331fb1dfb4;hb=f6feca16511c154f683895b3315974e399e7c13a;hp=ab5b4bd2fe8a07b9eef657085ca1fcd4114c645e;hpb=391659a08e30ce6430ecc569f99cc2556990d700;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git diff --git a/adaptors/x11/pixmap-render-surface-x.cpp b/adaptors/x11/pixmap-render-surface-x.cpp index ab5b4bd..a5cf8db 100644 --- a/adaptors/x11/pixmap-render-surface-x.cpp +++ b/adaptors/x11/pixmap-render-surface-x.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 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. @@ -28,9 +28,12 @@ #include #include +#include +#include // INTERNAL INCLUDES +#include #include #include #include @@ -46,13 +49,41 @@ extern Debug::Filter* gRenderSurfaceLogFilter; namespace ECore { +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 ), - mSyncMode(SYNC_MODE_NONE), - mSyncReceived(false) + mImpl( new Impl ) { Init( surface ); } @@ -62,20 +93,39 @@ PixmapRenderSurface::~PixmapRenderSurface() // 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]; + } + + 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& egl ) @@ -93,10 +143,13 @@ void PixmapRenderSurface::CreateEglSurface( EglInterface& egl ) Internal::Adaptor::EglImplementation& eglImpl = static_cast( 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( 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( mImpl->mX11Pixmaps[i] ); + mImpl->mEglSurfaces[i] = eglImpl.CreateSurfacePixmap( EGLNativePixmapType( pixmap ), mColorDepth ); // reinterpret_cast does not compile + } } void PixmapRenderSurface::DestroyEglSurface( EglInterface& egl ) @@ -104,38 +157,70 @@ void PixmapRenderSurface::DestroyEglSurface( EglInterface& egl ) DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); Internal::Adaptor::EglImplementation& eglImpl = static_cast( egl ); - eglImpl.DestroySurface(); + + 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( mImpl->mX11Pixmaps[i] ); + eglImpl.MakeCurrent( EGLNativePixmapType( pixmap ), mImpl->mEglSurfaces[i] ); + eglImpl.DestroySurface(); + } } bool PixmapRenderSurface::ReplaceEGLSurface( EglInterface& egl ) { DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter ); - // 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( mX11Pixmap ); + bool contextLost = false; + Internal::Adaptor::EglImplementation& eglImpl = static_cast( egl ); - return eglImpl.ReplaceSurfacePixmap( (EGLNativePixmapType)pixmap ); // reinterpret_cast does not compile + 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( mImpl->mX11Pixmaps[i] ); + contextLost = eglImpl.ReplaceSurfacePixmap( EGLNativePixmapType( pixmap ), mImpl->mEglSurfaces[i] ); // reinterpret_cast does not compile + } + + // 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( mImpl->mX11Pixmaps[mImpl->mProduceBufferIndex] ); + eglImpl.MakeCurrent( EGLNativePixmapType( pixmap ), mImpl->mEglSurfaces[mImpl->mProduceBufferIndex] ); + return contextLost; } void PixmapRenderSurface::StartRender() { - mSyncMode = SYNC_MODE_WAIT; } -bool PixmapRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction& ) +bool PixmapRenderSurface::PreRender( EglInterface& egl, Integration::GlAbstraction&, bool ) { - // nothing to do for pixmaps + // Nothing to do for pixmaps return true; } -void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface ) +void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface ) { // 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( 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( 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 ) { @@ -146,7 +231,7 @@ void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstract else { // as a fallback, send damage event. - Ecore_X_Drawable drawable = GetDrawable(); + Ecore_X_Drawable drawable = Ecore_X_Drawable( mImpl->mX11Pixmaps[mImpl->mProduceBufferIndex] ); if( drawable ) { @@ -163,80 +248,76 @@ void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstract // make a fixes region as updated area region = XFixesCreateRegion( display, &rect, 1 ); // add damage event to updated drawable - XDamageAdd( display, (Drawable)drawable, region ); + Drawable xdrawable( drawable ); // ecore type is unsigned int whereas in 64bit linux Drawable is long unsigned int + XDamageAdd( display, xdrawable, region ); XFixesDestroyRegion( display, region ); XFlush( display ); } } - AcquireLock( replacingSurface ? SYNC_MODE_NONE : SYNC_MODE_WAIT ); + if( mImpl->mThreadSynchronization ) + { + 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 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( mX11Pixmap, - ECORE_X_GC_VALUE_MASK_FOREGROUND, - &foreground ); - ecore_x_drawable_rectangle_fill( mX11Pixmap, gc, 0, 0, mPosition.width, mPosition.height ); + // 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 ); - DALI_ASSERT_ALWAYS( mX11Pixmap && "Failed to create X pixmap" ); + DALI_ASSERT_ALWAYS( gc && "CreateXRenderable(): failed to get gc" ); - // we SHOULD guarantee the xpixmap/x11 window was created in x server. - ecore_x_sync(); + ecore_x_drawable_rectangle_fill( mImpl->mX11Pixmaps[i], gc, 0, 0, mPosition.width, mPosition.height ); - ecore_x_gc_free(gc); -} + DALI_ASSERT_ALWAYS( mImpl->mX11Pixmaps[i] && "Failed to create X pixmap" ); -void PixmapRenderSurface::UseExistingRenderable( unsigned int surfaceId ) -{ - mX11Pixmap = static_cast< Ecore_X_Pixmap >( surfaceId ); -} + // we SHOULD guarantee the xpixmap/x11 window was created in x server. + ecore_x_sync(); -void PixmapRenderSurface::SetSyncMode( SyncMode syncMode ) -{ - mSyncMode = syncMode; + ecore_x_gc_free(gc); + } } -void PixmapRenderSurface::AcquireLock( SyncMode syncMode ) +void PixmapRenderSurface::UseExistingRenderable( unsigned int surfaceId ) { - 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; } 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