[Tizen] Implement partial update
authorHeeyong Song <heeyong.song@samsung.com>
Mon, 2 Mar 2020 05:28:07 +0000 (14:28 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Mon, 2 Mar 2020 05:28:10 +0000 (14:28 +0900)
Change-Id: I54d64942181b5436e847e2e664c3962ff7c133cb

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/adaptor-framework/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 f5d670d..14258c9
@@ -60,7 +60,8 @@ void TestApplication::CreateCore()
                                         mGlContextHelperAbstraction,
                                         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..37e1b3a
@@ -117,4 +117,13 @@ Vector4 TestRenderSurface::GetBackgroundColor()
   return mBackgroundColor;
 }
 
+void TestRenderSurface::SetDamagedRect( const Dali::DamagedRect& damagedRectArray, Dali::DamagedRect& mergedRectArray )
+{
+}
+
+int32_t TestRenderSurface::GetBufferAge()
+{
+  return 0;
+}
+
 } // Namespace dali
old mode 100644 (file)
new mode 100755 (executable)
index be38d00..c15d9eb
@@ -137,6 +137,16 @@ public:
    */
   virtual Vector4 GetBackgroundColor();
 
+  /**
+   * @copydoc Dali::Integration::RenderSurface::SetDamagedRect
+   */
+  virtual void SetDamagedRect( const Dali::DamagedRect& damagedRectArray, Dali::DamagedRect& mergedRectArray );
+
+  /**
+   * @copydoc Dali::Integration::RenderSurface::GetBufferAge
+   */
+  virtual int32_t GetBufferAge();
+
 private:
 
   /**
old mode 100644 (file)
new mode 100755 (executable)
index 687dd38..01260b2
@@ -179,6 +179,18 @@ public:
    */
   virtual Integration::StencilBufferAvailable GetStencilBufferRequired() = 0;
 
+  /**
+   * @brief Sets currentframe damaged rects
+   * @param[in] Sets currentframe damaged rects
+   * @param[out] return merged rect
+   */
+  virtual void SetDamagedRect( const Dali::DamagedRect& damagedRect, Dali::DamagedRect& mergedRectArray ) = 0;
+
+  /**
+   * @brief Gets buffer age
+   */
+  virtual int32_t GetBufferAge() = 0;
+
 public:
 
   void SetAdaptor( Dali::Internal::Adaptor::AdaptorInternalServices& adaptor )
index 4d1782fd9693ee3c507819aa92fa987fd75d908b..e01c5352a0ca0df111c35b71a2fd31b8825294fe 100755 (executable)
@@ -178,7 +178,8 @@ void Adaptor::Initialize( GraphicsFactory& graphicsFactory, Dali::Configuration:
                                   eglContextHelperImpl,
                                   ( 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 c653ab609adee5a057f3b5e9b99467d1628bb596..c0a8c2425f2bd7f3ede08d66a75a9adae6900d6e 100755 (executable)
 namespace
 {
   const uint32_t THRESHOLD_SWAPBUFFER_COUNT = 5;
-  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
@@ -63,7 +64,8 @@ namespace Adaptor
 
 EglImplementation::EglImplementation( int multiSamplingLevel,
                                       Integration::DepthBufferAvailable depthBufferRequired,
-                                      Integration::StencilBufferAvailable stencilBufferRequired )
+                                      Integration::StencilBufferAvailable stencilBufferRequired,
+                                      Integration::PartialUpdateAvailable partialUpdateAvailable )
 : mContextAttribs(),
   mEglNativeDisplay( 0 ),
   mEglNativeWindow( 0 ),
@@ -75,6 +77,7 @@ EglImplementation::EglImplementation( int multiSamplingLevel,
   mCurrentEglContext( EGL_NO_CONTEXT ),
   mMultiSamplingLevel( multiSamplingLevel ),
   mGlesVersion( 30 ),
+  mDamagedRectArray( 0 ),
   mColorDepth( COLOR_DEPTH_24 ),
   mGlesInitialized( false ),
   mIsOwnSurface( true ),
@@ -83,8 +86,26 @@ EglImplementation::EglImplementation( int multiSamplingLevel,
   mStencilBufferRequired( stencilBufferRequired == Integration::StencilBufferAvailable::TRUE ),
   mIsSurfacelessContextSupported( false ),
   mIsKhrCreateContextSupported( false ),
-  mSwapBufferCountAfterResume( 0 )
+  mSwapBufferCountAfterResume( 0 ),
+  mIsKhrPartialUpdateSupported( false ),
+  mPartialUpdateAvailable( partialUpdateAvailable == Integration::PartialUpdateAvailable::TRUE ),
+  mEglSetDamageRegionKHR( nullptr ),
+  mSwapBuffersWithDamage( nullptr )
 {
+  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 +156,16 @@ bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwn
       mIsKhrCreateContextSupported = true;
       extensionCheckCount++;
     }
+    if( currentExtension == EGL_KHR_PARTIAL_UPDATE )
+    {
+      mIsKhrPartialUpdateSupported = true;
+      extensionCheckCount++;
+    }
+  }
+
+  if( !mIsKhrPartialUpdateSupported )
+  {
+    mPartialUpdateAvailable = false;
   }
 
   mGlesInitialized = true;
@@ -309,6 +340,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
@@ -320,7 +376,14 @@ void EglImplementation::SwapBuffers( EGLSurface& eglSurface )
     }
 #endif //DALI_PROFILE_UBUNTU
 
-    eglSwapBuffers( mEglDisplay, eglSurface );
+    if( mPartialUpdateAvailable && mSwapBuffersWithDamage )
+    {
+      mSwapBuffersWithDamage( mEglDisplay, eglSurface, &mDamagedRectArray[0], mDamagedRectArray.size()/4 );
+    }
+    else
+    {
+      eglSwapBuffers( mEglDisplay, eglSurface );
+    }
 
 #ifndef DALI_PROFILE_UBUNTU
     if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT )
@@ -329,6 +392,33 @@ void EglImplementation::SwapBuffers( EGLSurface& eglSurface )
       mSwapBufferCountAfterResume++;
     }
 #endif //DALI_PROFILE_UBUNTU
+
+  }
+}
+
+
+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 efb9754..aefa9be
@@ -46,10 +46,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
@@ -123,6 +125,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
    */
@@ -238,6 +250,7 @@ private:
 
   int32_t              mMultiSamplingLevel;
   int32_t              mGlesVersion;
+  std::vector<int>     mDamagedRectArray;
 
   ColorDepth           mColorDepth;
 
@@ -248,8 +261,12 @@ private:
   bool                 mStencilBufferRequired;
   bool                 mIsSurfacelessContextSupported;
   bool                 mIsKhrCreateContextSupported;
+  uint32_t             mSwapBufferCountAfterResume;
+  bool                 mIsKhrPartialUpdateSupported;
+  bool                 mPartialUpdateAvailable;
 
-  uint32_t              mSwapBufferCountAfterResume;
+  PFNEGLSETDAMAGEREGIONKHRPROC mEglSetDamageRegionKHR;
+  PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC mSwapBuffersWithDamage;
 };
 
 } // namespace Adaptor
old mode 100644 (file)
new mode 100755 (executable)
index 7fea428..128692b
@@ -130,7 +130,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();
 }
@@ -391,6 +392,11 @@ bool EnvironmentOptions::StencilBufferRequired() const
   return mStencilBufferRequired;
 }
 
+bool EnvironmentOptions::PartialUpdateAvailable() const
+{
+  return mPartialUpdateAvailable;
+}
+
 void EnvironmentOptions::ParseEnvironmentOptions()
 {
   // get logging options
@@ -660,6 +666,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 f72ebdd..2ec1a09
@@ -316,6 +316,11 @@ public:
    */
   bool StencilBufferRequired() const;
 
+  /**
+   * @return whether the partial update is available.
+   */
+  bool PartialUpdateAvailable() const;
+
   /// Deleted copy constructor.
   EnvironmentOptions( const EnvironmentOptions& ) = delete;
 
@@ -383,6 +388,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 ca1a9c8..3290c8a
@@ -134,6 +134,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 9158f95..7fdb442
@@ -45,6 +45,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");
@@ -67,13 +68,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 );
@@ -409,6 +413,92 @@ 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;
+}
+
+
+void WindowRenderSurface::SetDamagedRect( const Dali::DamagedRect& damagedRect, Dali::DamagedRect& mergedRect )
+{
+  auto eglGraphics = static_cast<EglGraphics *>( mGraphics );
+  std::vector<int32_t> rectArray;
+  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() )
+  {
+    mergedRect.x = rectArray[0];
+    mergedRect.y = rectArray[1];
+    mergedRect.width = rectArray[2];
+    mergedRect.height = rectArray[3];
+  }
+}
+
+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
@@ -449,6 +539,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 b27414a..5353b72
@@ -204,6 +204,16 @@ public: // from Dali::Integration::RenderSurface
    */
   virtual Integration::StencilBufferAvailable GetStencilBufferRequired() override;
 
+  /**
+   * @copydoc Dali::Integration::RenderSurface::SetDamagedRect()
+   */
+  virtual void SetDamagedRect( const Dali::DamagedRect& damagedRect, Dali::DamagedRect& mergedRect ) override;
+
+  /**
+   * @copydoc Dali::Integration::RenderSurface::GetBufferAge()
+   */
+  virtual int32_t GetBufferAge() override;
+
 private:
 
   /**
@@ -221,6 +231,11 @@ private:
    */
   void ProcessRotationRequest();
 
+  /*
+   *  @brief MergeRect
+   */
+  std::vector<int32_t> MergeRect( const Rect<int32_t>& damagedRectArray, int bufferAge );
+
 protected:
 
   // Undefined
@@ -245,6 +260,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;
@@ -254,6 +271,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 876e989..76e0d89
@@ -227,6 +227,15 @@ bool NativeRenderSurfaceEcoreWl::PreRender( bool )
   return true;
 }
 
+void NativeRenderSurfaceEcoreWl::SetDamagedRect( const Dali::DamagedRect& damagedRect, Dali::DamagedRect& mergedRect )
+{
+}
+
+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 bba6553..9964e2a
@@ -159,6 +159,18 @@ public: // from Dali::Integration::RenderSurface
    */
   virtual Integration::StencilBufferAvailable GetStencilBufferRequired() override;
 
+  /**
+   * @copydoc Dali::Integration::RenderSurface::SetDamagedRect()
+   */
+  virtual void SetDamagedRect( const Dali::DamagedRect& damagedRect, Dali::DamagedRect& mergedRect ) override;
+
+  /**
+   * @copydoc Dali::Integration::RenderSurface::GetBufferAge()
+   */
+  virtual int32_t GetBufferAge() override;
+
+
+
 private:
 
   /**
old mode 100644 (file)
new mode 100755 (executable)
index f54c3ea..5e7a8cf
@@ -231,6 +231,15 @@ bool PixmapRenderSurfaceEcoreX::PreRender( bool )
   return true;
 }
 
+void PixmapRenderSurfaceEcoreX::SetDamagedRect( const Dali::DamagedRect& damagedRect, Dali::DamagedRect& mergedRect )
+{
+}
+
+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 05e850f..a8851c8
@@ -169,6 +169,16 @@ private: // from PixmapRenderSurface
    */
   virtual void UseExistingRenderable( unsigned int surfaceId ) override;
 
+  /**
+   * @copydoc Dali::Integration::RenderSurface::SetDamagedRect()
+   */
+  virtual void SetDamagedRect( const Dali::DamagedRect& damagedRect, Dali::DamagedRect& mergedRect ) override;
+
+  /**
+   * @copydoc Dali::Integration::RenderSurface::GetBufferAge()
+   */
+  virtual int32_t GetBufferAge() override;
+
 private:
 
   /**