Revert "[Tizen] Revert "Support screen rotation""
[platform/core/uifw/dali-adaptor.git] / adaptors / x11 / pixmap-render-surface-x.cpp
index 816d2d5..a5cf8db 100644 (file)
@@ -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.
 
 #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>
@@ -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<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& egl )
@@ -104,38 +157,70 @@ void PixmapRenderSurface::DestroyEglSurface( EglInterface& egl )
   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
 
   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( 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<XPixmap>( 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<XPixmap>( mX11Pixmap );
+  bool contextLost = false;
+
   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( 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<XPixmap>( 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<XPixmap>( 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<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 )
   {
@@ -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,83 +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 );
+    // 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( gc && "CreateXRenderable(): failed to get gc" );
+    DALI_ASSERT_ALWAYS( gc && "CreateXRenderable(): failed to get gc" );
 
-  ecore_x_drawable_rectangle_fill( mX11Pixmap, gc, 0, 0, mPosition.width, mPosition.height );
+    ecore_x_drawable_rectangle_fill( mImpl->mX11Pixmaps[i], gc, 0, 0, mPosition.width, mPosition.height );
 
-  DALI_ASSERT_ALWAYS( mX11Pixmap && "Failed to create X pixmap" );
+    DALI_ASSERT_ALWAYS( mImpl->mX11Pixmaps[i] && "Failed to create X pixmap" );
 
-  // we SHOULD guarantee the xpixmap/x11 window was created in x server.
-  ecore_x_sync();
+    // we SHOULD guarantee the xpixmap/x11 window was created in x server.
+    ecore_x_sync();
 
-  ecore_x_gc_free(gc);
+    ecore_x_gc_free(gc);
+  }
 }
 
 void PixmapRenderSurface::UseExistingRenderable( unsigned int surfaceId )
 {
-  mX11Pixmap = static_cast< Ecore_X_Pixmap >( surfaceId );
-}
-
-void PixmapRenderSurface::SetSyncMode( SyncMode syncMode )
-{
-  mSyncMode = syncMode;
 }
 
-void PixmapRenderSurface::AcquireLock( SyncMode syncMode )
+void PixmapRenderSurface::ReleaseLock()
 {
-  boost::unique_lock< boost::mutex > lock( mSyncMutex );
-
-  // wait for sync
-  if( syncMode != SYNC_MODE_NONE &&
-      mSyncMode != SYNC_MODE_NONE &&
-      !mSyncReceived )
+  if( mImpl->mThreadSynchronization )
   {
-    mSyncNotify.wait( lock );
+    mImpl->mThreadSynchronization->PostRenderComplete();
   }
-  mSyncReceived = false;
 }
 
-void PixmapRenderSurface::ReleaseLock()
+RenderSurface::Type PixmapRenderSurface::GetSurfaceType()
 {
-  {
-    boost::unique_lock< boost::mutex > lock( mSyncMutex );
-    mSyncReceived = true;
-  }
-
-  // wake render thread if it was waiting for the notify
-  mSyncNotify.notify_all();
+  return RenderSurface::ECORE_RENDER_SURFACE;
 }
 
 } // namespace ECore