Fix FrameBuffer sync issue, etc. 61/207561/15
authorJiyun Yang <ji.yang@samsung.com>
Fri, 7 Jun 2019 06:56:38 +0000 (15:56 +0900)
committerJiyun Yang <ji.yang@samsung.com>
Fri, 21 Jun 2019 04:35:06 +0000 (13:35 +0900)
(1) Fix FrameBuffer sync issue

Render::FrameBuffer has mSurface but the Surface can be modified by main thread.
API such as Render::FrameBuffer::GetWidth() returned mSurface's property to the update+render thread.
This broke FrameBuffer sync between threads.

To fix this, make Render::FrameBuffer no longer use mSurface's width, height and backgroundColor directly.
Instead, it stores those values and update it through messages in the update manager.

(2) Fix Window resize issue

Since multi-window introduced, the update+render thread has not received
the resizing informtion of each window, so it couldn't pass resizing flag properly
to the surface when rendering (PreRender/PostRender).

Since Window::SetSize() can be called anytime even in the middle of updating and rendering,
the update+render thread can not use resizing information in the Surface directly.
-> The core should passes a surface resizement information to the update+render thread by messaging.

After (1), the core gets a method that passes Surface resizement info to the udpate+render thread
and it solves problems.

(3) Move the backgroundColor to Scene from RenderSurface

Change-Id: I385a45a46de681c3c0656cdb4a59a9f8f464d975
Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
dali/integration-api/render-surface.h
dali/integration-api/scene.cpp
dali/integration-api/scene.h
dali/internal/common/core-impl.cpp
dali/internal/event/common/scene-impl.cpp
dali/internal/event/common/scene-impl.h
dali/internal/event/rendering/frame-buffer-impl.cpp
dali/internal/event/rendering/frame-buffer-impl.h
dali/internal/render/renderers/render-surface-frame-buffer.cpp
dali/internal/render/renderers/render-surface-frame-buffer.h

index 17f22e9..2270fc2 100644 (file)
@@ -183,18 +183,6 @@ public:
    */
   virtual Integration::StencilBufferAvailable GetStencilBufferRequired() = 0;
 
-  /**
-   * @brief Sets the background color of the surface.
-   * @param[in] color The new background color
-   */
-  virtual void SetBackgroundColor(Vector4 color) = 0;
-
-  /**
-   * @brief Gets the background color of the surface.
-   * @return The background color
-   */
-  virtual Vector4 GetBackgroundColor() = 0;
-
 private:
 
   /**
index e5c7f2f..b2a4922 100644 (file)
@@ -89,6 +89,16 @@ Vector2 Scene::GetDpi() const
   return GetImplementation(*this).GetDpi();
 }
 
+void Scene::SetBackgroundColor( const Vector4& color )
+{
+  GetImplementation(*this).SetBackgroundColor( color );
+}
+
+Vector4 Scene::GetBackgroundColor() const
+{
+  return GetImplementation(*this).GetBackgroundColor();
+}
+
 RenderTaskList Scene::GetRenderTaskList() const
 {
   return RenderTaskList( &GetImplementation(*this).GetRenderTaskList() );
index 0e4dbbd..2128b47 100755 (executable)
@@ -21,6 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali/public-api/object/handle.h>
 #include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector4.h>
 
 namespace Dali
 {
@@ -149,6 +150,20 @@ public:
   Vector2 GetDpi() const;
 
   /**
+   * @brief Sets the background color.
+   *
+   * @param[in] color The new background color
+   */
+  void SetBackgroundColor( const Vector4& color );
+
+  /**
+   * @brief Gets the background color of the render surface.
+   *
+   * @return The background color
+   */
+  Vector4 GetBackgroundColor() const;
+
+  /**
    * @brief Retrieves the list of render-tasks.
    *
    * @return A valid handle to a RenderTaskList
index 1a09947..c1e7fde 100644 (file)
@@ -197,7 +197,7 @@ void Core::SurfaceResized( Integration::RenderSurface* surface )
   {
     if( (*iter)->GetSurface() == surface )
     {
-      (*iter)->SetSurface( *surface );
+      (*iter)->SurfaceResized();
     }
   }
 }
index 4d00fd0..a944d35 100644 (file)
@@ -63,6 +63,7 @@ Scene::Scene( const Size& size )
   mSize( size ),
   mSurfaceSize( Vector2::ZERO ),
   mDpi( Vector2::ZERO ),
+  mBackgroundColor( DEFAULT_BACKGROUND_COLOR ),
   mDepthTreeDirty( false ),
   mEventProcessor( *this, ThreadLocalStorage::GetInternal()->GetGestureEventProcessor() )
 {
@@ -195,34 +196,54 @@ void Scene::SetSurface( Integration::RenderSurface& surface )
   mSurface = &surface;
   if ( mSurface )
   {
-    mSurfaceSize.width = static_cast<float>( mSurface->GetPositionSize().width );
-    mSurfaceSize.height = static_cast<float>( mSurface->GetPositionSize().height );
+    RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask( 0u );
 
-    mSize.width = mSurfaceSize.width;
-    mSize.height = mSurfaceSize.height;
+    mFrameBuffer = Dali::Internal::FrameBuffer::New( surface, Dali::FrameBuffer::Attachment::NONE );
+    defaultRenderTask->SetFrameBuffer( mFrameBuffer );
 
-    // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position.
-    mDefaultCamera->SetPerspectiveProjection( mSurfaceSize );
+    SurfaceResized();
+  }
+}
 
-    mRootLayer->SetSize( mSize.width, mSize.height );
+void Scene::SurfaceResized()
+{
+  if( mSurface )
+  {
+    const float fWidth = static_cast<float>( mSurface->GetPositionSize().width );
+    const float fHeight = static_cast<float>( mSurface->GetPositionSize().height );
 
-    ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
-    SceneGraph::UpdateManager& updateManager = tls->GetUpdateManager();
-    SetDefaultSurfaceRectMessage( updateManager, Rect<int32_t>( 0, 0, static_cast<int32_t>( mSurfaceSize.width ), static_cast<int32_t>( mSurfaceSize.height ) ) ); // truncated
+    if( ( fabsf( mSurfaceSize.width - fWidth ) > Math::MACHINE_EPSILON_1 ) || ( fabsf( mSurfaceSize.height - fHeight ) > Math::MACHINE_EPSILON_1 ) )
+    {
+      Rect<int32_t> newSize( 0, 0, static_cast<int32_t>( mSurface->GetPositionSize().width ), static_cast<int32_t>( mSurface->GetPositionSize().height ) );
 
-    RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask( 0u );
+      mSurfaceSize.width = fWidth;
+      mSurfaceSize.height = fHeight;
 
-    // if single render task to screen then set its viewport parameters
-    if( 1 == mRenderTaskList->GetTaskCount() )
-    {
-      if( !defaultRenderTask->GetTargetFrameBuffer() )
+      mSize.width = mSurfaceSize.width;
+      mSize.height = mSurfaceSize.height;
+
+      // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position.
+      mDefaultCamera->SetPerspectiveProjection( mSurfaceSize );
+
+      mRootLayer->SetSize( mSize.width, mSize.height );
+
+      ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
+      SceneGraph::UpdateManager& updateManager = tls->GetUpdateManager();
+      SetDefaultSurfaceRectMessage( updateManager, newSize ); // truncated
+
+      RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask( 0u );
+
+      // if single render task to screen then set its viewport parameters
+      if( 1 == mRenderTaskList->GetTaskCount() )
       {
-        defaultRenderTask->SetViewport( Viewport( 0, 0, static_cast<int32_t>( mSurfaceSize.width ), static_cast<int32_t>( mSurfaceSize.height ) ) ); // truncated
+        if( !defaultRenderTask->GetTargetFrameBuffer() )
+        {
+          defaultRenderTask->SetViewport( newSize ); // truncated
+        }
       }
-    }
 
-    mFrameBuffer = Dali::Internal::FrameBuffer::New( surface, Dali::FrameBuffer::Attachment::NONE );
-    defaultRenderTask->SetFrameBuffer( mFrameBuffer );
+      defaultRenderTask->GetFrameBuffer()->SetSize( static_cast<uint32_t>( newSize.width ), static_cast<uint32_t>( newSize.height ) );
+    }
   }
 }
 
@@ -266,17 +287,19 @@ void Scene::RebuildDepthTree()
   }
 }
 
-void Scene::SetBackgroundColor(Vector4 color)
+void Scene::SetBackgroundColor( const Vector4& color )
 {
+  mBackgroundColor = color;
+
   if( mSurface )
   {
-    mSurface->SetBackgroundColor( color );
+    mRenderTaskList->GetTask( 0u )->GetFrameBuffer()->SetBackgroundColor( color );
   }
 }
 
 Vector4 Scene::GetBackgroundColor() const
 {
-  return mSurface ? mSurface->GetBackgroundColor() : DEFAULT_BACKGROUND_COLOR;
+  return mBackgroundColor;
 }
 
 void Scene::EmitKeyEventSignal(const KeyEvent& event)
index b94175a..fb09efd 100644 (file)
@@ -120,6 +120,11 @@ public:
   void SetSurface( Integration::RenderSurface& surface );
 
   /**
+   * Notify the surface has been resized.
+   */
+  void SurfaceResized();
+
+  /**
    * @copydoc Dali::Integration::Scene::Discard
    */
   void Discard();
@@ -159,10 +164,10 @@ public:
   void RebuildDepthTree();
 
   /**
-   * @brief Sets the background color of the render surface.
+   * @brief Sets the background color of the render surface.
    * @param[in] color The new background color
    */
-  void SetBackgroundColor(Vector4 color);
+  void SetBackgroundColor( const Vector4& color );
 
   /**
    * @brief Gets the background color of the render surface.
@@ -263,6 +268,8 @@ private:
 
   Vector2 mDpi;
 
+  Vector4 mBackgroundColor;
+
   LayerPtr mRootLayer;
 
   // Ordered list of currently on-stage layers
index 2b42e41..9c8345d 100644 (file)
@@ -106,6 +106,25 @@ Texture* FrameBuffer::GetColorTexture()
   return mIsSurfaceBacked ? nullptr : mColor.Get();
 }
 
+void FrameBuffer::SetSize( uint32_t width, uint32_t height )
+{
+  mWidth = width;
+  mHeight = height;
+
+  if( mRenderObject->IsSurfaceBacked() )
+  {
+    SetFrameBufferSizeMessage( mEventThreadServices.GetUpdateManager(), static_cast<Render::SurfaceFrameBuffer*>( mRenderObject ), width, height );
+  }
+}
+
+void FrameBuffer::SetBackgroundColor( const Vector4& color )
+{
+  if( mRenderObject->IsSurfaceBacked() )
+  {
+    SetFrameBufferBackgroundColorMessage( mEventThreadServices.GetUpdateManager(), static_cast<Render::SurfaceFrameBuffer*>( mRenderObject ), color );
+  }
+}
+
 FrameBuffer::~FrameBuffer()
 {
   if( EventThreadServices::IsCoreRunning() && mRenderObject )
index 3531c0f..341b284 100644 (file)
@@ -63,8 +63,8 @@ public:
   /**
    * @brief Create a new FrameBuffer
    *
-   * @param[in] renderSurface  The render surface
-   * @param[in] attachments    The attachments comprising the format of the FrameBuffer (bit-mask)
+   * @param[in] renderSurface   The render surface
+   * @param[in] attachments     The attachments comprising the format of the FrameBuffer (bit-mask)
    * @return A smart-pointer to the newly allocated Texture.
    */
   static FrameBufferPtr New( Dali::Integration::RenderSurface& renderSurface, Mask attachments );
@@ -91,6 +91,19 @@ public:
    */
   Texture* GetColorTexture();
 
+  /**
+   * @brief Sets the frame buffer size.
+   * @param[in] width The width size
+   * @param[in] height The height size
+   */
+  void SetSize( uint32_t width, uint32_t height );
+
+  /**
+   * @brief Sets the background color
+   * @param[in] color The new background color
+   */
+  void SetBackgroundColor( const Vector4& color );
+
 private: // implementation
 
   /**
index 7cc38bb..4b63c33 100644 (file)
@@ -30,7 +30,11 @@ namespace Render
 SurfaceFrameBuffer::SurfaceFrameBuffer( Integration::RenderSurface* surface )
 : FrameBuffer(),
   mSurface( surface ),
-  mContext( nullptr )
+  mContext( nullptr ),
+  mWidth( mSurface->GetPositionSize().width ),
+  mHeight( mSurface->GetPositionSize().height ),
+  mBackgroundColor( 0.f, 0.f, 0.f, 1.f ),
+  mSizeChanged( false )
 {
 }
 
@@ -58,23 +62,26 @@ void SurfaceFrameBuffer::Initialize(Context& context)
 
 void SurfaceFrameBuffer::Bind( Context& context )
 {
-  mSurface->PreRender( false );
+  mSurface->PreRender( mSizeChanged );
+
   context.BindFramebuffer( GL_FRAMEBUFFER, 0u );
 }
 
 uint32_t SurfaceFrameBuffer::GetWidth() const
 {
-  return mSurface->GetPositionSize().width;
+  return mWidth;
 }
 
 uint32_t SurfaceFrameBuffer::GetHeight() const
 {
-  return mSurface->GetPositionSize().height;
+  return mHeight;
 }
 
 void SurfaceFrameBuffer::PostRender()
 {
-  mSurface->PostRender( false, false, false );
+  mSurface->PostRender( false, false, mSizeChanged );
+
+  mSizeChanged = false;
 }
 
 Context* SurfaceFrameBuffer::GetContext()
@@ -94,7 +101,19 @@ Integration::StencilBufferAvailable SurfaceFrameBuffer::GetStencilBufferRequired
 
 Vector4 SurfaceFrameBuffer::GetBackgroundColor()
 {
-  return mSurface->GetBackgroundColor();
+  return mBackgroundColor;
+}
+
+void SurfaceFrameBuffer::SetSize( uint32_t width, uint32_t height )
+{
+  mWidth = width;
+  mHeight = height;
+  mSizeChanged = true;
+}
+
+void SurfaceFrameBuffer::SetBackgroundColor( const Vector4& color )
+{
+  mBackgroundColor = color;
 }
 
 } //Render
index 576ea65..ebe7eb5 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 // INTERNAL INCLUDES
+#include <dali/internal/update/manager/update-manager.h>
 #include <dali/internal/render/renderers/render-frame-buffer.h>
 #include <dali/integration-api/render-surface.h>
 
@@ -82,6 +83,19 @@ public:
    */
   bool IsSurfaceBacked() override { return true; };
 
+  /**
+   * @brief Sets the frame buffer size.
+   * @param[in] width The width size
+   * @param[in] height The height size
+   */
+  void SetSize( uint32_t width, uint32_t height );
+
+  /**
+   * @brief Sets the background color.
+   * @param[in] color The new background color
+   */
+  void SetBackgroundColor( const Vector4& color );
+
 public:
 
   /**
@@ -117,8 +131,35 @@ private:
 
   Integration::RenderSurface* mSurface;   ///< The render surface
   Context*                    mContext;   ///< The context holding the GL state of rendering for the surface backed frame buffer
+
+  uint32_t                    mWidth;
+  uint32_t                    mHeight;
+  Vector4                     mBackgroundColor;
+  bool                        mSizeChanged;
 };
 
+// Messages for FrameBuffer
+inline void SetFrameBufferSizeMessage( SceneGraph::UpdateManager& updateManager, SurfaceFrameBuffer* surfaceFrameBuffer, uint32_t width, uint32_t height )
+{
+  typedef MessageValue2< SurfaceFrameBuffer, uint32_t, uint32_t  > LocalType;
+
+  // Reserve some memory inside the message queue
+  uint32_t* slot = updateManager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( surfaceFrameBuffer, &SurfaceFrameBuffer::SetSize, width, height );
+}
+
+inline void SetFrameBufferBackgroundColorMessage( SceneGraph::UpdateManager& updateManager, SurfaceFrameBuffer* surfaceFrameBuffer, const Vector4& color )
+{
+  typedef MessageValue1< SurfaceFrameBuffer, Vector4 > LocalType;
+
+  // Reserve some memory inside the message queue
+  uint32_t* slot = updateManager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( surfaceFrameBuffer, &SurfaceFrameBuffer::SetBackgroundColor, color );
+}
 
 } // namespace Render