[Tizen] Implement partial update
authorJoogab Yun <joogab.yun@samsung.com>
Mon, 15 Apr 2019 07:27:57 +0000 (16:27 +0900)
committerJoogab Yun <joogab.yun@samsung.com>
Tue, 10 Sep 2019 09:30:38 +0000 (18:30 +0900)
1. It works when the DALI_PARTIAL_UPDATE_AVAILABLE environment variable is set.

Change-Id: Ibfed04cc509e7935de4aa131fcf385a15b019606

18 files changed:
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp [changed mode: 0644->0755]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-render-surface.cpp [changed mode: 0644->0755]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-render-surface.h [changed mode: 0644->0755]
dali/integration-api/render-surface-interface.h [changed mode: 0644->0755]
dali/internal/adaptor/common/adaptor-impl.cpp
dali/internal/graphics/common/graphics-interface.h [changed mode: 0644->0755]
dali/internal/graphics/gles/egl-graphics.cpp [changed mode: 0644->0755]
dali/internal/graphics/gles/egl-implementation.cpp
dali/internal/graphics/gles/egl-implementation.h [changed mode: 0644->0755]
dali/internal/system/common/environment-options.cpp [changed mode: 0644->0755]
dali/internal/system/common/environment-options.h [changed mode: 0644->0755]
dali/internal/system/common/environment-variables.h [changed mode: 0644->0755]
dali/internal/window-system/common/window-render-surface.cpp [changed mode: 0644->0755]
dali/internal/window-system/common/window-render-surface.h [changed mode: 0644->0755]
dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp [changed mode: 0644->0755]
dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.h [changed mode: 0644->0755]
dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.cpp [changed mode: 0644->0755]
dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.h [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 338b71f..8dbdc62
@@ -63,7 +63,8 @@ void TestApplication::CreateCore()
                                         mDataRetentionPolicy,
                                         Integration::RenderToFrameBuffer::FALSE,
                                         Integration::DepthBufferAvailable::TRUE,
-                                        Integration::StencilBufferAvailable::TRUE );
+                                        Integration::StencilBufferAvailable::TRUE,
+                                        Integration::PartialUpdateAvailable::FALSE );
 
   mCore->ContextCreated();
 
old mode 100644 (file)
new mode 100755 (executable)
index 066b37e..84381d3
@@ -117,4 +117,14 @@ Vector4 TestRenderSurface::GetBackgroundColor()
   return mBackgroundColor;
 }
 
+Rect<int32_t> TestRenderSurface::SetDamagedRect( const Rect<int32_t>& damagedRectArray )
+{
+  return damagedRectArray;
+}
+
+int32_t TestRenderSurface::GetBufferAge()
+{
+  return 0;
+}
+
 } // Namespace dali
old mode 100644 (file)
new mode 100755 (executable)
index be38d00..2fed827
@@ -137,6 +137,16 @@ public:
    */
   virtual Vector4 GetBackgroundColor();
 
+  /**
+   * @copydoc Dali::Integration::RenderSurface::SetDamagedRect
+   */
+  virtual Rect<int32_t> SetDamagedRect( const Rect<int32_t>& damagedRectArray );
+
+  /**
+   * @copydoc Dali::Integration::RenderSurface::GetBufferAge
+   */
+  virtual int32_t GetBufferAge();
+
 private:
 
   /**
old mode 100644 (file)
new mode 100755 (executable)
index 3fc746c..a356cbb
@@ -181,6 +181,16 @@ public:
    */
   virtual Integration::StencilBufferAvailable GetStencilBufferRequired() = 0;
 
+  /**
+   * @brief Sets currentframe updated/damaged rects
+   */
+  virtual Rect<int32_t> SetDamagedRect( const Rect<int32_t>& damagedRect ) = 0;
+
+  /**
+   * @brief Gets buffer age
+   */
+  virtual int32_t GetBufferAge() = 0;
+
 public:
 
   void SetAdaptor( Dali::Internal::Adaptor::AdaptorInternalServices& adaptor )
index 3416ed8f2eeb3a7fee7577d3e7971680570f9a34..cd41ed781f5a0c1642e83d0ccb7d4cff43732623 100755 (executable)
@@ -184,7 +184,8 @@ void Adaptor::Initialize( GraphicsFactory& graphicsFactory, Dali::Configuration:
                                   dataRetentionPolicy ,
                                   ( 0u != mEnvironmentOptions->GetRenderToFboInterval() ) ? Integration::RenderToFrameBuffer::TRUE : Integration::RenderToFrameBuffer::FALSE,
                                   mGraphics->GetDepthBufferRequired(),
-                                  mGraphics->GetStencilBufferRequired() );
+                                  mGraphics->GetStencilBufferRequired(),
+                                  mGraphics->PartialUpdateAvailable() );
 
   defaultWindow->SetAdaptor( Get() );
 
old mode 100644 (file)
new mode 100755 (executable)
index 5e80ef7..9b5d4cf
@@ -43,7 +43,8 @@ public:
    */
   GraphicsInterface()
 : mDepthBufferRequired( Integration::DepthBufferAvailable::FALSE ),
-  mStencilBufferRequired( Integration::StencilBufferAvailable::FALSE )
+  mStencilBufferRequired( Integration::StencilBufferAvailable::FALSE ),
+  mPartialUpdateAvailable( Integration::PartialUpdateAvailable::FALSE )
   {
   };
 
@@ -76,6 +77,15 @@ public:
     return mStencilBufferRequired;
   };
 
+  /**
+   * Get whether the partial update is available
+   * @return TRUE if the partial update is available
+   */
+  Integration::PartialUpdateAvailable PartialUpdateAvailable()
+  {
+    return mPartialUpdateAvailable;
+  };
+
 protected:
   /**
    * Virtual protected destructor - no deletion through this interface
@@ -87,6 +97,7 @@ protected:
 
   Integration::DepthBufferAvailable mDepthBufferRequired;       ///< Whether the depth buffer is required
   Integration::StencilBufferAvailable mStencilBufferRequired;   ///< Whether the stencil buffer is required
+  Integration::PartialUpdateAvailable mPartialUpdateAvailable; ///Whether the partial update is available
 };
 
 } // Adaptor
old mode 100644 (file)
new mode 100755 (executable)
index 406e69c..2ce631e
@@ -62,6 +62,7 @@ void EglGraphics::Initialize( EnvironmentOptions* environmentOptions )
 
   mDepthBufferRequired = static_cast< Integration::DepthBufferAvailable >( environmentOptions->DepthBufferRequired() );
   mStencilBufferRequired = static_cast< Integration::StencilBufferAvailable >( environmentOptions->StencilBufferRequired() );
+  mPartialUpdateAvailable = static_cast< Integration::PartialUpdateAvailable >( environmentOptions->PartialUpdateAvailable() );
 
   mMultiSamplingLevel = environmentOptions->GetMultiSamplingLevel();
 
@@ -72,7 +73,7 @@ void EglGraphics::Initialize( EnvironmentOptions* environmentOptions )
 
 EglInterface* EglGraphics::Create()
 {
-  mEglImplementation = Utils::MakeUnique< EglImplementation >( mMultiSamplingLevel, mDepthBufferRequired, mStencilBufferRequired );
+  mEglImplementation = Utils::MakeUnique< EglImplementation >( mMultiSamplingLevel, mDepthBufferRequired, mStencilBufferRequired, mPartialUpdateAvailable );
   mEglImageExtensions = Utils::MakeUnique< EglImageExtensions >( mEglImplementation.get() );
 
   mEglSync->Initialize( mEglImplementation.get() ); // The sync impl needs the EglDisplay
index ae95d258df2d039606fd66e029276adbb0656115..55834c9a90aa1fe66c56e51c0eac33fabd40d7e1 100755 (executable)
 
 namespace
 {
-  const uint32_t CHECK_EXTENSION_NUMBER = 2;
+  const uint32_t CHECK_EXTENSION_NUMBER = 3;
   const std::string EGL_KHR_SURFACELESS_CONTEXT = "EGL_KHR_surfaceless_context";
   const std::string EGL_KHR_CREATE_CONTEXT = "EGL_KHR_create_context";
+  const std::string EGL_KHR_PARTIAL_UPDATE = "EGL_KHR_partial_update";
 }
 
 namespace Dali
@@ -62,7 +63,8 @@ namespace Adaptor
 
 EglImplementation::EglImplementation( int multiSamplingLevel,
                                       Integration::DepthBufferAvailable depthBufferRequired,
-                                      Integration::StencilBufferAvailable stencilBufferRequired )
+                                      Integration::StencilBufferAvailable stencilBufferRequired,
+                                      Integration::PartialUpdateAvailable partialUpdateAvailable )
 : mContextAttribs(),
   mEglNativeDisplay( 0 ),
   mEglNativeWindow( 0 ),
@@ -74,6 +76,7 @@ EglImplementation::EglImplementation( int multiSamplingLevel,
   mCurrentEglContext( EGL_NO_CONTEXT ),
   mMultiSamplingLevel( multiSamplingLevel ),
   mGlesVersion( 30 ),
+  mDamagedRectArray( 0 ),
   mColorDepth( COLOR_DEPTH_24 ),
   mGlesInitialized( false ),
   mIsOwnSurface( true ),
@@ -82,8 +85,24 @@ EglImplementation::EglImplementation( int multiSamplingLevel,
   mStencilBufferRequired( stencilBufferRequired == Integration::StencilBufferAvailable::TRUE ),
   mIsSurfacelessContextSupported( false ),
   mIsKhrCreateContextSupported( false ),
-  mIsFirstFrameAfterResume( false )
+  mIsFirstFrameAfterResume( false ),
+  mIsKhrPartialUpdateSupported( false ),
+  mPartialUpdateAvailable( partialUpdateAvailable == Integration::PartialUpdateAvailable::TRUE )
 {
+  if( mPartialUpdateAvailable )
+  {
+    mEglSetDamageRegionKHR =  reinterpret_cast< PFNEGLSETDAMAGEREGIONKHRPROC >( eglGetProcAddress( "eglSetDamageRegionKHR" ) );
+    mSwapBuffersWithDamage = reinterpret_cast< PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC >( eglGetProcAddress( "eglSwapBuffersWithDamageEXT" ) );
+    if( !mEglSetDamageRegionKHR || !mSwapBuffersWithDamage )
+    {
+      mPartialUpdateAvailable = false;
+      DALI_LOG_ERROR("Initialization of partial update failed.\n");
+    }
+    else
+    {
+      DALI_LOG_RELEASE_INFO("Initialization of partial update success!\n");
+    }
+  }
 }
 
 EglImplementation::~EglImplementation()
@@ -135,6 +154,16 @@ bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwn
       mIsKhrCreateContextSupported = true;
       extensionCheckCount++;
     }
+    if( currentExtension == EGL_KHR_PARTIAL_UPDATE )
+    {
+      mIsKhrPartialUpdateSupported = true;
+      extensionCheckCount++;
+    }
+  }
+
+  if( !mIsKhrPartialUpdateSupported )
+  {
+    mPartialUpdateAvailable = false;
   }
 
   // We want to display this information all the time, so use the LogMessage directly
@@ -307,6 +336,31 @@ bool EglImplementation::IsGlesInitialized() const
   return mGlesInitialized;
 }
 
+
+const char* GetEglErrorString(EGLint error)
+{
+    switch(error)
+    {
+    case EGL_SUCCESS: return "No error";
+    case EGL_NOT_INITIALIZED: return "EGL not initialized or failed to initialize";
+    case EGL_BAD_ACCESS: return "Resource inaccessible";
+    case EGL_BAD_ALLOC: return "Cannot allocate resources";
+    case EGL_BAD_ATTRIBUTE: return "Unrecognized attribute or attribute value";
+    case EGL_BAD_CONTEXT: return "Invalid EGL context";
+    case EGL_BAD_CONFIG: return "Invalid EGL frame buffer configuration";
+    case EGL_BAD_CURRENT_SURFACE: return "Current surface is no longer valid";
+    case EGL_BAD_DISPLAY: return "Invalid EGL display";
+    case EGL_BAD_SURFACE: return "Invalid surface";
+    case EGL_BAD_MATCH: return "Inconsistent arguments";
+    case EGL_BAD_PARAMETER: return "Invalid argument";
+    case EGL_BAD_NATIVE_PIXMAP: return "Invalid native pixmap";
+    case EGL_BAD_NATIVE_WINDOW: return "Invalid native window";
+    case EGL_CONTEXT_LOST: return "Context lost";
+    }
+    return "Unknown error ";
+}
+
+
 void EglImplementation::SwapBuffers( EGLSurface& eglSurface )
 {
   if ( eglSurface != EGL_NO_SURFACE ) // skip if using surfaceless context
@@ -316,7 +370,40 @@ void EglImplementation::SwapBuffers( EGLSurface& eglSurface )
       DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers: First SwapBuffers call.\n" );
       mIsFirstFrameAfterResume = false;
     }
-    eglSwapBuffers( mEglDisplay, eglSurface );
+    if( mPartialUpdateAvailable && mSwapBuffersWithDamage )
+    {
+      mSwapBuffersWithDamage( mEglDisplay, eglSurface, &mDamagedRectArray[0], mDamagedRectArray.size()/4 );
+    }
+    else
+    {
+      eglSwapBuffers( mEglDisplay, eglSurface );
+    }
+  }
+}
+
+
+int EglImplementation::GetBufferAge( EGLSurface& eglSurface )
+{
+  int bufferAge = 0;
+  if ( eglSurface != EGL_NO_SURFACE && mIsKhrPartialUpdateSupported )
+  {
+    if( !eglQuerySurface(mEglDisplay, eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge) )
+    {
+      DALI_LOG_ERROR("EglImplementation::GetBufferAge() eglQuerySurface %s ",  GetEglErrorString(eglGetError()) );
+    }
+  }
+  return bufferAge;
+}
+
+void EglImplementation::SetDamagedRect( std::vector<int> damagedRectArray, EGLSurface& eglSurface )
+{
+  mDamagedRectArray = damagedRectArray;
+  if ( eglSurface != EGL_NO_SURFACE && mPartialUpdateAvailable && mEglSetDamageRegionKHR )
+  {
+    if( !mEglSetDamageRegionKHR( mEglDisplay, eglSurface, &damagedRectArray[0], damagedRectArray.size() / 4 ) )
+    {
+      DALI_LOG_ERROR("EglImplementation::mEglSetDamageRegionKHR() error %s ",  GetEglErrorString(eglGetError()) );
+    }
   }
 }
 
old mode 100644 (file)
new mode 100755 (executable)
index c0cf433..a8da4e4
@@ -48,10 +48,12 @@ public:
    * @param[in] multiSamplingLevel The Multi-sampling level required
    * @param[in] depthBufferRequired Whether the depth buffer is required
    * @param[in] stencilBufferRequired Whether the stencil buffer is required
+   * @param[in] partialUpdateAvailable Whether the partial update is available
    */
   EglImplementation( int multiSamplingLevel,
                      Integration::DepthBufferAvailable depthBufferRequired,
-                     Integration::StencilBufferAvailable stencilBufferRequired );
+                     Integration::StencilBufferAvailable stencilBufferRequired,
+                     Integration::PartialUpdateAvailable partialUpdateAvailable );
 
   /**
    * Destructor
@@ -125,6 +127,16 @@ public:
    */
   virtual void SwapBuffers( EGLSurface& eglSurface );
 
+ /**
+  * Get current buffer age
+  */
+  virtual int GetBufferAge( EGLSurface& eglSurface );
+
+  /**
+   * Set Damaged rect for Partial update
+  */
+  virtual void SetDamagedRect( std::vector<int> damagedRectArray, EGLSurface& eglSurface );
+
   /**
    * Performs an OpenGL copy buffers command
    */
@@ -240,6 +252,7 @@ private:
 
   int32_t              mMultiSamplingLevel;
   int32_t              mGlesVersion;
+  std::vector<int>     mDamagedRectArray;
 
   ColorDepth           mColorDepth;
 
@@ -252,6 +265,11 @@ private:
   bool                 mIsKhrCreateContextSupported;
 
   bool                 mIsFirstFrameAfterResume;
+  bool                 mIsKhrPartialUpdateSupported;
+  bool                 mPartialUpdateAvailable;
+
+  PFNEGLSETDAMAGEREGIONKHRPROC mEglSetDamageRegionKHR;
+  PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC mSwapBuffersWithDamage;
 };
 
 } // namespace Adaptor
old mode 100644 (file)
new mode 100755 (executable)
index 23bec81..d6d54cd
@@ -125,7 +125,8 @@ EnvironmentOptions::EnvironmentOptions()
   mThreadingMode( ThreadingMode::COMBINED_UPDATE_RENDER ),
   mGlesCallAccumulate( false ),
   mDepthBufferRequired( DEFAULT_DEPTH_BUFFER_REQUIRED_SETTING ),
-  mStencilBufferRequired( DEFAULT_STENCIL_BUFFER_REQUIRED_SETTING )
+  mStencilBufferRequired( DEFAULT_STENCIL_BUFFER_REQUIRED_SETTING ),
+  mPartialUpdateAvailable( false )
 {
   ParseEnvironmentOptions();
 }
@@ -361,6 +362,11 @@ bool EnvironmentOptions::StencilBufferRequired() const
   return mStencilBufferRequired;
 }
 
+bool EnvironmentOptions::PartialUpdateAvailable() const
+{
+  return mPartialUpdateAvailable;
+}
+
 void EnvironmentOptions::ParseEnvironmentOptions()
 {
   // get logging options
@@ -600,6 +606,15 @@ void EnvironmentOptions::ParseEnvironmentOptions()
       mStencilBufferRequired = false;
     }
   }
+
+  int partialUpdateRequired( -1 );
+  if( GetIntegerEnvironmentVariable( DALI_ENV_PARTIAL_UPDATE_AVAILABLE, partialUpdateRequired ) )
+  {
+    if( partialUpdateRequired > 0 )
+    {
+      mPartialUpdateAvailable = true;
+    }
+  }
 }
 
 } // Adaptor
old mode 100644 (file)
new mode 100755 (executable)
index 253ea7e..3fe351b
@@ -291,6 +291,11 @@ public:
    */
   bool StencilBufferRequired() const;
 
+  /**
+   * @return whether the partial update is available.
+   */
+  bool PartialUpdateAvailable() const;
+
   /// Deleted copy constructor.
   EnvironmentOptions( const EnvironmentOptions& ) = delete;
 
@@ -353,6 +358,7 @@ private: // Data
   bool mGlesCallAccumulate;                       ///< Whether or not to accumulate gles call statistics
   bool mDepthBufferRequired;                      ///< Whether the depth buffer is required
   bool mStencilBufferRequired;                    ///< Whether the stencil buffer is required
+  bool mPartialUpdateAvailable;                   ///< whether the partial update is available
   std::unique_ptr<TraceManager> mTraceManager;    ///< TraceManager
 };
 
old mode 100644 (file)
new mode 100755 (executable)
index 3d63c00..6c790de
@@ -122,6 +122,8 @@ namespace Adaptor
 
 #define DALI_ENV_DPI_VERTICAL "DALI_DPI_VERTICAL"
 
+#define DALI_ENV_PARTIAL_UPDATE_AVAILABLE "DALI_PARTIAL_UPDATE_AVAILABLE"
+
 } // namespace Adaptor
 
 } // namespace Internal
old mode 100644 (file)
new mode 100755 (executable)
index e4bb890..eff8745
@@ -46,6 +46,7 @@ namespace
 {
 
 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
+const int TILE_SIZE = 16u;  ///< Unit of tile size at GPU driver
 
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE");
@@ -68,13 +69,16 @@ WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any s
   mOutputTransformedSignal(),
   mRotationAngle( 0 ),
   mScreenRotationAngle( 0 ),
+  mBufferAge( 0 ),
+  mPreBufferAge( 0 ),
   mOwnSurface( false ),
   mRotationSupported( false ),
   mRotationFinished( true ),
   mScreenRotationFinished( true ),
   mResizeFinished( true ),
   mDpiHorizontal( 0 ),
-  mDpiVertical( 0 )
+  mDpiVertical( 0 ),
+  mPreDamagedRect()
 {
   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
   Initialize( surface );
@@ -411,6 +415,95 @@ bool WindowRenderSurface::PreRender( bool resizingSurface )
   return true;
 }
 
+std::vector<int32_t> WindowRenderSurface::MergeRect( const Rect<int32_t>& damagedRect, int bufferAge )
+{
+  std::vector<int32_t> mergedRectArray;
+  // merge bounding
+  int dx1 = mPositionSize.width, dx2 = 0, dy1 = mPositionSize.height, dy2 = 0;
+  int checkWidth = mPositionSize.width - TILE_SIZE;
+  int checkHeight = mPositionSize.height - TILE_SIZE;
+
+  dx1 = std::min( damagedRect.x, dx1 );
+  dx2 = std::max( damagedRect.x + damagedRect.width, dx2);
+  dy1 = std::min( damagedRect.y, dy1 );
+  dy2 = std::max( damagedRect.y + damagedRect.height, dy2 );
+
+  for( int j = 0; j <= bufferAge; j++ )
+  {
+    if( !mPreDamagedRect[j].IsEmpty() )
+    {
+      dx1 = std::min( mPreDamagedRect[j].x, dx1 );
+      dx2 = std::max( mPreDamagedRect[j].x + mPreDamagedRect[j].width, dx2);
+      dy1 = std::min( mPreDamagedRect[j].y, dy1 );
+      dy2 = std::max( mPreDamagedRect[j].y + mPreDamagedRect[j].height, dy2 );
+
+      if( dx1 < TILE_SIZE && dx2 > checkWidth && dy1 < TILE_SIZE && dy2 > checkHeight )
+      {
+        dx1 = 0, dx2 = mPositionSize.width, dy1 = 0, dy2 = mPositionSize.height;
+        break;
+      }
+    }
+  }
+
+  dx1 = TILE_SIZE * (dx1 / TILE_SIZE);
+  dy1 = TILE_SIZE * (dy1 / TILE_SIZE);
+  dx2 = TILE_SIZE * ((dx2 + TILE_SIZE - 1) / TILE_SIZE);
+  dy2 = TILE_SIZE * ((dy2 + TILE_SIZE - 1) / TILE_SIZE);
+
+  mergedRectArray.push_back( dx1 );
+  mergedRectArray.push_back( dy1 );
+  mergedRectArray.push_back( dx2 - dx1 );
+  mergedRectArray.push_back( dy2 - dy1 );
+
+  return mergedRectArray;
+}
+
+
+Rect<int32_t> WindowRenderSurface::SetDamagedRect( const Rect<int32_t>& damagedRect )
+{
+  auto eglGraphics = static_cast<EglGraphics *>( mGraphics );
+  std::vector<int32_t> rectArray;
+  Rect<int32_t> mergedDamagedRect;
+  if( eglGraphics )
+  {
+    Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+
+    rectArray = MergeRect( damagedRect, mBufferAge );
+
+    mPreDamagedRect[4] = std::move( mPreDamagedRect[3] );
+    mPreDamagedRect[3] = std::move( mPreDamagedRect[2] );
+    mPreDamagedRect[2] = std::move( mPreDamagedRect[1] );
+    mPreDamagedRect[1] = std::move( mPreDamagedRect[0] );
+    mPreDamagedRect[0] = std::move( damagedRect );
+
+    eglImpl.SetDamagedRect( rectArray, mEGLSurface );
+  }
+
+  if( !rectArray.empty() )
+  {
+    mergedDamagedRect.x = rectArray[0];
+    mergedDamagedRect.y = rectArray[1];
+    mergedDamagedRect.width = rectArray[2];
+    mergedDamagedRect.height = rectArray[3];
+  }
+
+  return mergedDamagedRect;
+}
+
+int32_t WindowRenderSurface::GetBufferAge()
+{
+  int result = mBufferAge = 0;
+  auto eglGraphics = static_cast<EglGraphics *>( mGraphics );
+  if( eglGraphics )
+  {
+    Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+    mBufferAge = eglImpl.GetBufferAge( mEGLSurface );;
+    result = ( mBufferAge != mPreBufferAge ) ? 0 : mBufferAge;
+    mPreBufferAge = mBufferAge;
+  }
+  return result;
+}
+
 void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
 {
   // Inform the gl implementation that rendering has finished before informing the surface
@@ -445,6 +538,7 @@ void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, b
     }
 
     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+
     eglImpl.SwapBuffers( mEGLSurface );
 
     if( mRenderNotification )
old mode 100644 (file)
new mode 100755 (executable)
index 2401a39..41d7ccb
@@ -210,6 +210,16 @@ public: // from Dali::Integration::RenderSurface
    */
   virtual Integration::StencilBufferAvailable GetStencilBufferRequired() override;
 
+  /**
+   * @copydoc Dali::Integration::RenderSurface::SetDamagedRect()
+   */
+  virtual Rect<int32_t> SetDamagedRect( const Rect<int32_t>& damagedRectArray ) override;
+
+  /**
+   * @copydoc Dali::Integration::RenderSurface::GetBufferAge()
+   */
+  virtual int32_t GetBufferAge() override;
+
 private:
 
   /**
@@ -227,6 +237,11 @@ private:
    */
   void ProcessRotationRequest();
 
+  /*
+   *  @brief MergeRect
+   */
+  std::vector<int32_t> MergeRect( const Rect<int32_t>& damagedRectArray, int bufferAge );
+
 protected:
 
   // Undefined
@@ -251,6 +266,8 @@ private: // Data
   OutputSignalType                mOutputTransformedSignal;
   int                             mRotationAngle;
   int                             mScreenRotationAngle;
+  int                             mBufferAge;
+  int                             mPreBufferAge;
   bool                            mOwnSurface;         ///< Whether we own the surface (responsible for deleting it)
   bool                            mRotationSupported;
   bool                            mRotationFinished;
@@ -260,6 +277,7 @@ private: // Data
   uint32_t                        mDpiHorizontal;
   uint32_t                        mDpiVertical;
 
+  Rect<int32_t>                   mPreDamagedRect[5];  ///< The GPU driver can has up to four buffers. And one is for area calculation.
 }; // class WindowRenderSurface
 
 } // namespace Adaptor
old mode 100644 (file)
new mode 100755 (executable)
index e69e8f1..f8c6e98
@@ -227,6 +227,16 @@ bool NativeRenderSurfaceEcoreWl::PreRender( bool )
   return true;
 }
 
+Rect<int32_t> NativeRenderSurfaceEcoreWl::SetDamagedRect( const Rect<int32_t>& damagedRect )
+{
+  return damagedRect;
+}
+
+int32_t NativeRenderSurfaceEcoreWl::GetBufferAge()
+{
+  return 0;
+}
+
 void NativeRenderSurfaceEcoreWl::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
 {
   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
old mode 100644 (file)
new mode 100755 (executable)
index 00e7133..abb6b17
@@ -159,6 +159,18 @@ public: // from Dali::Integration::RenderSurface
    */
   virtual Integration::StencilBufferAvailable GetStencilBufferRequired() override;
 
+  /**
+   * @copydoc Dali::Integration::RenderSurface::SetDamagedRect()
+   */
+  virtual Rect<int32_t> SetDamagedRect( const Rect<int32_t>& damagedRect ) override;
+
+  /**
+   * @copydoc Dali::Integration::RenderSurface::GetBufferAge()
+   */
+  virtual int32_t GetBufferAge() override;
+
+
+
 private:
 
   /**
old mode 100644 (file)
new mode 100755 (executable)
index 41a44da..652ea95
@@ -234,6 +234,16 @@ bool PixmapRenderSurfaceEcoreX::PreRender( bool )
   return true;
 }
 
+Rect<int32_t> PixmapRenderSurfaceEcoreX::SetDamagedRect( const Rect<int32_t>& damagedRect )
+{
+  return damagedRect;
+}
+
+int32_t PixmapRenderSurfaceEcoreX::GetBufferAge()
+{
+  return 0;
+}
+
 void PixmapRenderSurfaceEcoreX::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
 {
   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
old mode 100644 (file)
new mode 100755 (executable)
index c9d8da7..4542ffa
@@ -170,6 +170,16 @@ private: // from PixmapRenderSurface
    */
   virtual void UseExistingRenderable( unsigned int surfaceId ) override;
 
+  /**
+   * @copydoc Dali::Integration::RenderSurface::SetDamagedRect()
+   */
+  virtual Rect<int32_t> SetDamagedRect( const Rect<int32_t>& damagedRect ) override;
+
+  /**
+   * @copydoc Dali::Integration::RenderSurface::GetBufferAge()
+   */
+  virtual int32_t GetBufferAge() override;
+
 private:
 
   /**