Partial update implementation, first phase. 78/230878/25
authorAnton Obzhirov <a.obzhirov@samsung.com>
Tue, 14 Apr 2020 15:00:16 +0000 (16:00 +0100)
committerAnton Obzhirov <a.obzhirov@samsung.com>
Fri, 19 Jun 2020 15:33:46 +0000 (16:33 +0100)
Change-Id: I222a1972d5727f6e01bb941b08339c38aad1546a

26 files changed:
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.h
automated-tests/src/dali-adaptor/utc-Dali-Window.cpp
dali/devel-api/adaptor-framework/window-devel.cpp
dali/devel-api/adaptor-framework/window-devel.h
dali/integration-api/adaptor-framework/render-surface-interface.h
dali/integration-api/adaptor-framework/scene-holder-impl.cpp
dali/internal/adaptor/common/adaptor-impl.cpp
dali/internal/adaptor/common/combined-update-render-controller.cpp
dali/internal/adaptor/common/combined-update-render-controller.h
dali/internal/graphics/common/graphics-interface.h
dali/internal/graphics/gles/egl-graphics.cpp
dali/internal/graphics/gles/egl-graphics.h
dali/internal/graphics/gles/egl-implementation.cpp
dali/internal/graphics/gles/egl-implementation.h
dali/internal/system/common/environment-options.cpp
dali/internal/system/common/environment-options.h
dali/internal/system/common/environment-variables.h
dali/internal/window-system/common/window-impl.cpp
dali/internal/window-system/common/window-impl.h
dali/internal/window-system/common/window-render-surface.cpp
dali/internal/window-system/common/window-render-surface.h
dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp
dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.h
dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.cpp
dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.h

index e8c0d12..b2a3fb9 100644 (file)
@@ -26,13 +26,15 @@ TestApplication::TestApplication( uint32_t surfaceWidth,
                                   uint32_t surfaceHeight,
                                   uint32_t  horizontalDpi,
                                   uint32_t  verticalDpi,
-                                  bool initialize )
+                                  bool initialize,
+                                  bool enablePartialUpdate )
 : mCore( NULL ),
   mSurfaceWidth( surfaceWidth ),
   mSurfaceHeight( surfaceHeight ),
   mFrame( 0u ),
   mDpi{ horizontalDpi, verticalDpi },
-  mLastVSyncTime(0u)
+  mLastVSyncTime(0u),
+  mPartialUpdateEnabled(enablePartialUpdate)
 {
   if( initialize )
   {
@@ -59,7 +61,8 @@ void TestApplication::CreateCore()
                                         mGlContextHelperAbstraction,
                                         Integration::RenderToFrameBuffer::FALSE,
                                         Integration::DepthBufferAvailable::TRUE,
-                                        Integration::StencilBufferAvailable::TRUE );
+                                        Integration::StencilBufferAvailable::TRUE,
+                                        mPartialUpdateEnabled ? Integration::PartialUpdateAvailable::TRUE : Integration::PartialUpdateAvailable::FALSE );
 
   mCore->ContextCreated();
 
@@ -193,8 +196,8 @@ bool TestApplication::Render( uint32_t intervalMilliseconds, const char* locatio
   mRenderStatus.SetNeedsPostRender( false );
 
   mCore->PreRender( mRenderStatus, false /*do not force clear*/, false /*do not skip rendering*/ );
-  mCore->RenderScene( mRenderStatus, mScene, true /*render the off-screen buffers*/);
-  mCore->RenderScene( mRenderStatus, mScene, false /*render the surface*/);
+  mCore->RenderScene( mRenderStatus, mScene, true /*render the off-screen buffers*/ );
+  mCore->RenderScene( mRenderStatus, mScene, false /*render the surface*/ );
   mCore->PostRender( false /*do not skip rendering*/ );
 
   mFrame++;
@@ -202,6 +205,27 @@ bool TestApplication::Render( uint32_t intervalMilliseconds, const char* locatio
   return mStatus.KeepUpdating() || mRenderStatus.NeedsUpdate();
 }
 
+bool TestApplication::PreRenderWithPartialUpdate(uint32_t intervalMilliseconds, const char* location, std::vector<Rect<int>>& damagedRects)
+{
+  DoUpdate(intervalMilliseconds, location);
+
+  mCore->PreRender(mRenderStatus, false /*do not force clear*/, false /*do not skip rendering*/ );
+  mCore->PreRender(mScene, damagedRects);
+
+  return mStatus.KeepUpdating() || mRenderStatus.NeedsUpdate();
+}
+
+bool TestApplication::RenderWithPartialUpdate(std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect)
+{
+  mCore->RenderScene(mRenderStatus, mScene, true /*render the off-screen buffers*/, clippingRect);
+  mCore->RenderScene(mRenderStatus, mScene, false /*render the surface*/, clippingRect);
+  mCore->PostRender(false /*do not skip rendering*/);
+
+  mFrame++;
+
+  return mStatus.KeepUpdating() || mRenderStatus.NeedsUpdate();
+}
+
 uint32_t TestApplication::GetUpdateStatus()
 {
   return mStatus.KeepUpdating();
@@ -227,8 +251,8 @@ bool TestApplication::RenderOnly( )
 {
   // Update Time values
   mCore->PreRender( mRenderStatus, false /*do not force clear*/, false /*do not skip rendering*/ );
-  mCore->RenderScene( mRenderStatus, mScene, true /*render the off-screen buffers*/);
-  mCore->RenderScene( mRenderStatus, mScene, false /*render the surface*/);
+  mCore->RenderScene( mRenderStatus, mScene, true /*render the off-screen buffers*/ );
+  mCore->RenderScene( mRenderStatus, mScene, false /*render the surface*/ );
   mCore->PostRender( false /*do not skip rendering*/ );
 
   mFrame++;
index e96f759..1df0743 100644 (file)
@@ -51,7 +51,8 @@ public:
                    uint32_t surfaceHeight = DEFAULT_SURFACE_HEIGHT,
                    uint32_t horizontalDpi = DEFAULT_HORIZONTAL_DPI,
                    uint32_t verticalDpi   = DEFAULT_VERTICAL_DPI,
-                   bool initialize = true );
+                   bool initialize = true,
+                   bool enablePartialUpdate = false );
 
   void Initialize();
   void CreateCore();
@@ -69,6 +70,8 @@ public:
   void ProcessEvent(const Integration::Event& event);
   void SendNotification();
   bool Render( uint32_t intervalMilliseconds = DEFAULT_RENDER_INTERVAL, const char* location=NULL );
+  bool PreRenderWithPartialUpdate(uint32_t intervalMilliseconds, const char* location, std::vector<Rect<int>>& damagedRects);
+  bool RenderWithPartialUpdate(std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect);
   uint32_t GetUpdateStatus();
   bool UpdateOnly( uint32_t intervalMilliseconds = DEFAULT_RENDER_INTERVAL );
   bool RenderOnly( );
@@ -108,6 +111,7 @@ protected:
 
   struct { uint32_t x; uint32_t y; } mDpi;
   uint32_t mLastVSyncTime;
+  bool mPartialUpdateEnabled;
   static bool mLoggingEnabled;
 };
 
index 4b14df2..cb7de36 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <dali/dali.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/internal/system/linux/dali-ecore-x.h>
 #include <dali-test-suite-utils.h>
 
@@ -412,3 +413,20 @@ int UtcDaliWindowFocusChangedSignalN(void)
 
   END_TEST;
 }
+
+int UtcDaliWindowPartialUpdate(void)
+{
+  Dali::Window window;
+  try
+  {
+    std::vector<Rect<int>> damagedAreas;
+    DevelWindow::SetDamagedAreas(window, damagedAreas);
+    DALI_TEST_CHECK( false ); // Should not reach here!
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
index b9fadbb..44e9801 100755 (executable)
@@ -148,6 +148,11 @@ int32_t GetNativeId( Window window )
   return GetImplementation( window ).GetNativeId();
 }
 
+void SetDamagedAreas(Window window, std::vector<Dali::Rect<int>>& areas)
+{
+  GetImplementation(window).SetDamagedAreas(areas);
+}
+
 } // namespace DevelWindow
 
 } // namespace Dali
index 958b940..1eb3501 100755 (executable)
@@ -2,7 +2,7 @@
 #define DALI_WINDOW_DEVEL_H
 
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
  *
  */
 
+// EXTERNAL INCLUDES
+
 // INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/adaptor-framework/window.h>
 
 namespace Dali
@@ -250,6 +253,16 @@ DALI_ADAPTOR_API void SetAvailableOrientations( Window window, const Dali::Vecto
  */
 DALI_ADAPTOR_API int32_t GetNativeId( Window window );
 
+/**
+ * @brief Sets damaged areas of the window.
+ *
+ * This API is for setting static damaged areas of the window for partial update.
+ *
+ * @param[in] window The window instance
+ * @param[in] areas The damaged areas list to set
+ */
+DALI_ADAPTOR_API void SetDamagedAreas(Window window, std::vector<Dali::Rect<int>>& areas);
+
 } // namespace DevelWindow
 
 } // namespace Dali
index 25ad128..e148662 100644 (file)
@@ -20,6 +20,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/integration-api/core-enumerations.h>
+#include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/math/vector4.h>
 #include <dali/public-api/math/rect.h>
 #include <dali/public-api/object/any.h>
@@ -136,9 +137,10 @@ public:
    * If the operation fails, then Core::Render should not be called until there is
    * a surface to render onto.
    * @param[in] resizingSurface True if the surface is being resized
+   * @param[in] damagedRects List of damaged rects this render pass
    * @return True if the operation is successful, False if the operation failed
    */
-  virtual bool PreRender( bool resizingSurface ) = 0;
+  virtual bool PreRender( bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect ) = 0;
 
   /**
    * @brief Invoked by render thread after Core::Render
@@ -146,7 +148,8 @@ public:
    * @param[in] replacingSurface True if the surface is being replaced.
    * @param[in] resizingSurface True if the surface is being resized.
    */
-  virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ) = 0;
+  virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects ) = 0;
+
   /**
    * @brief Invoked by render thread when the thread should be stop
    */
index 7162a1c..5bbe94b 100644 (file)
@@ -31,6 +31,7 @@
 // INTERNAL INCLUDES
 #include <dali/internal/adaptor/common/adaptor-impl.h>
 #include <dali/internal/adaptor/common/lifecycle-observer.h>
+#include <dali/internal/graphics/gles/egl-graphics.h>
 #include <dali/internal/input/common/key-impl.h>
 #include <dali/internal/input/common/physical-keyboard-impl.h>
 
@@ -208,6 +209,13 @@ void SceneHolder::SurfaceResized()
 {
   PositionSize surfacePositionSize = mSurface->GetPositionSize();
   mScene.SurfaceResized( static_cast<float>( surfacePositionSize.width ), static_cast<float>( surfacePositionSize.height ) );
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
 }
 
 Dali::RenderSurfaceInterface* SceneHolder::GetSurface() const
@@ -220,6 +228,13 @@ void SceneHolder::SetBackgroundColor( const Vector4& color )
   if( mScene )
   {
     mScene.SetBackgroundColor( color );
+
+    GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+    EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+    if (eglGraphics)
+    {
+      eglGraphics->SetFullSwapNextFrame();
+    }
   }
 }
 
index a48eb5f..58f9c85 100755 (executable)
@@ -181,7 +181,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->GetPartialUpdateRequired() );
 
   defaultWindow->SetAdaptor( Get() );
 
index b310671..b514cb6 100644 (file)
@@ -745,18 +745,35 @@ void CombinedUpdateRenderController::UpdateRenderThread()
 
           windowSurface->InitializeGraphics();
 
+          // clear previous frame damaged render items rects, buffer history is tracked on surface level
+          mDamagedRects.clear();
+
+          // If user damaged areas are not set
+          if (!eglImpl.DamageAreasSet())
+          {
+            // Collect damage rects
+            mCore.PreRender( scene, mDamagedRects );
+          }
+
           // Render off-screen frame buffers first if any
           mCore.RenderScene( windowRenderStatus, scene, true );
 
-          // Switch to the EGL context of the surface
-          windowSurface->PreRender( surfaceResized ); // Switch GL context
+          Rect<int> clippingRect; // Empty for fbo rendering
+
+          // Switch to the EGL context of the surface, merge damaged areas for previous frames
+          windowSurface->PreRender( surfaceResized, mDamagedRects, clippingRect ); // Switch GL context
+
+          if (clippingRect.IsEmpty())
+          {
+            mDamagedRects.clear();
+          }
 
           // Render the surface
-          mCore.RenderScene( windowRenderStatus, scene, false );
+          mCore.RenderScene( windowRenderStatus, scene, false, clippingRect );
 
           if( windowRenderStatus.NeedsPostRender() )
           {
-            windowSurface->PostRender( false, false, surfaceResized ); // Swap Buffer
+            windowSurface->PostRender( false, false, surfaceResized, mDamagedRects ); // Swap Buffer with damage
           }
         }
       }
index 965479e..8dfd4eb 100644 (file)
@@ -391,6 +391,8 @@ private:
   volatile unsigned int             mUploadWithoutRendering;           ///< Will be set to upload the resource only (with no rendering)
 
   volatile unsigned int             mFirstFrameAfterResume;            ///< Will be set to check the first frame after resume (for log)
+
+  std::vector<Rect<int>>            mDamagedRects;                     ///< Keeps collected damaged render items rects for one render pass
 };
 
 } // namespace Adaptor
index 93c1b2f..4404fab 100644 (file)
@@ -42,8 +42,9 @@ public:
    * Constructor
    */
   GraphicsInterface()
-: mDepthBufferRequired( Integration::DepthBufferAvailable::FALSE ),
-  mStencilBufferRequired( Integration::StencilBufferAvailable::FALSE )
+  : mDepthBufferRequired( Integration::DepthBufferAvailable::FALSE ),
+    mStencilBufferRequired( Integration::StencilBufferAvailable::FALSE ),
+    mPartialUpdateRequired( Integration::PartialUpdateAvailable::FALSE )
   {
   };
 
@@ -81,11 +82,20 @@ public:
     return mStencilBufferRequired;
   };
 
+  /**
+   * Get whether the stencil buffer is required
+   * @return TRUE if the stencil buffer is required
+   */
+  Integration::PartialUpdateAvailable GetPartialUpdateRequired()
+  {
+    return mPartialUpdateRequired;
+  };
 
 protected:
 
   Integration::DepthBufferAvailable mDepthBufferRequired;       ///< Whether the depth buffer is required
   Integration::StencilBufferAvailable mStencilBufferRequired;   ///< Whether the stencil buffer is required
+  Integration::PartialUpdateAvailable mPartialUpdateRequired;   ///< Whether the partial update is required
 };
 
 } // Adaptor
index 406e69c..e13ce0b 100644 (file)
@@ -62,6 +62,7 @@ void EglGraphics::Initialize( EnvironmentOptions* environmentOptions )
 
   mDepthBufferRequired = static_cast< Integration::DepthBufferAvailable >( environmentOptions->DepthBufferRequired() );
   mStencilBufferRequired = static_cast< Integration::StencilBufferAvailable >( environmentOptions->StencilBufferRequired() );
+  mPartialUpdateRequired = static_cast< Integration::PartialUpdateAvailable >( environmentOptions->PartialUpdateRequired() );
 
   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, mPartialUpdateRequired );
   mEglImageExtensions = Utils::MakeUnique< EglImageExtensions >( mEglImplementation.get() );
 
   mEglSync->Initialize( mEglImplementation.get() ); // The sync impl needs the EglDisplay
@@ -128,6 +129,16 @@ EglImageExtensions* EglGraphics::GetImageExtensions()
   return mEglImageExtensions.get();
 }
 
+void EglGraphics::SetDamagedAreas(std::vector<Dali::Rect<int>>& areas)
+{
+  mEglImplementation->SetDamageAreas(areas);
+}
+
+void EglGraphics::SetFullSwapNextFrame()
+{
+  mEglImplementation->SetFullSwapNextFrame();
+}
+
 } // Adaptor
 } // Internal
 } // Dali
index 8ee45bc..410395c 100644 (file)
@@ -126,6 +126,16 @@ public:
   EglImageExtensions* GetImageExtensions();
 
   /**
+   * Sets fixed damaged areas for partial rendering. This overrides automatic partial rendering.
+   */
+  void SetDamagedAreas( std::vector<Dali::Rect<int>>& areas );
+
+  /**
+   * Instructs egl implementation to do full swap regardless of stored data, resets the data.
+   */
+  void SetFullSwapNextFrame();
+
+  /**
    * @copydoc Dali::Internal::Adaptor::GraphicsInterface::Destroy()
    */
   void Destroy() override;
index 38851f9..3710dd1 100755 (executable)
@@ -63,7 +63,8 @@ namespace Adaptor
 
 EglImplementation::EglImplementation( int multiSamplingLevel,
                                       Integration::DepthBufferAvailable depthBufferRequired,
-                                      Integration::StencilBufferAvailable stencilBufferRequired )
+                                      Integration::StencilBufferAvailable stencilBufferRequired ,
+                                      Integration::PartialUpdateAvailable partialUpdateRequired )
 : mContextAttribs(),
   mEglNativeDisplay( 0 ),
   mEglNativeWindow( 0 ),
@@ -81,9 +82,14 @@ EglImplementation::EglImplementation( int multiSamplingLevel,
   mIsWindow( true ),
   mDepthBufferRequired( depthBufferRequired == Integration::DepthBufferAvailable::TRUE ),
   mStencilBufferRequired( stencilBufferRequired == Integration::StencilBufferAvailable::TRUE ),
+  mPartialUpdateRequired( partialUpdateRequired == Integration::PartialUpdateAvailable::TRUE ),
   mIsSurfacelessContextSupported( false ),
   mIsKhrCreateContextSupported( false ),
-  mSwapBufferCountAfterResume( 0 )
+  mSwapBufferCountAfterResume( 0 ),
+  mEglSetDamageRegionKHR( 0 ),
+  mEglSwapBuffersWithDamageKHR( 0 ),
+  mBufferAge( 0 ),
+  mFullSwapNextFrame( true )
 {
 }
 
@@ -169,6 +175,18 @@ bool EglImplementation::CreateContext()
   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
   DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS));
 
+  mEglSetDamageRegionKHR = reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(eglGetProcAddress("eglSetDamageRegionKHR"));
+  if (!mEglSetDamageRegionKHR)
+  {
+    DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n");
+    mPartialUpdateRequired = false;
+  }
+  mEglSwapBuffersWithDamageKHR = reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(eglGetProcAddress("eglSwapBuffersWithDamageKHR"));
+  if (!mEglSwapBuffersWithDamageKHR)
+  {
+    DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n");
+    mPartialUpdateRequired = false;
+  }
   return true;
 }
 
@@ -190,6 +208,18 @@ bool EglImplementation::CreateWindowContext( EGLContext& eglContext )
 
   mEglWindowContexts.push_back( eglContext );
 
+  mEglSetDamageRegionKHR = reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(eglGetProcAddress("eglSetDamageRegionKHR"));
+  if (!mEglSetDamageRegionKHR)
+  {
+    DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n");
+    mPartialUpdateRequired = false;
+  }
+  mEglSwapBuffersWithDamageKHR = reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(eglGetProcAddress("eglSwapBuffersWithDamageKHR"));
+  if (!mEglSwapBuffersWithDamageKHR)
+  {
+    DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n");
+    mPartialUpdateRequired = false;
+  }
   return true;
 }
 
@@ -321,7 +351,266 @@ void EglImplementation::SwapBuffers( EGLSurface& eglSurface )
     }
 #endif //DALI_PROFILE_UBUNTU
 
+    // DALI_LOG_ERROR("EglImplementation::SwapBuffers()\n");
     eglSwapBuffers( mEglDisplay, eglSurface );
+    mFullSwapNextFrame = false;
+
+#ifndef DALI_PROFILE_UBUNTU
+    if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT )
+    {
+      DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers finished.\n" );
+      mSwapBufferCountAfterResume++;
+    }
+#endif //DALI_PROFILE_UBUNTU
+  }
+}
+
+EGLint EglImplementation::GetBufferAge(EGLSurface& eglSurface) const
+{
+  EGLint age = 0;
+  eglQuerySurface(mEglDisplay, eglSurface, EGL_BUFFER_AGE_EXT, &age);
+  if (age < 0)
+  {
+    DALI_LOG_ERROR("eglQuerySurface(%d)\n", eglGetError());
+    age = 0;
+  }
+
+  // 0 - invalid buffer
+  // 1, 2, 3
+  if (age > 3)
+  {
+    DALI_LOG_ERROR("EglImplementation::GetBufferAge() buffer age %d > 3\n", age);
+    age = 0; // shoudn't be more than 3 back buffers, if there is just reset, I don't want to add extra history level
+  }
+
+  return age;
+}
+
+bool EglImplementation::DamageAreasSet() const
+{
+  return (mDamagedAreas.size() ? true : false);
+}
+
+void EglImplementation::SetDamageAreas( std::vector<Dali::Rect<int>>& damagedAreas )
+{
+  mFullSwapNextFrame = true;
+  mDamagedAreas = damagedAreas;
+}
+
+void EglImplementation::SetFullSwapNextFrame()
+{
+  mFullSwapNextFrame = true;
+}
+
+void mergeRects(Rect<int>& mergingRect, const std::vector<Rect<int>>& rects)
+{
+  uint32_t i = 0;
+  if (mergingRect.IsEmpty())
+  {
+    for (;i < rects.size(); i++)
+    {
+      if (!rects[i].IsEmpty())
+      {
+        mergingRect = rects[i];
+        break;
+      }
+    }
+  }
+
+  for (;i < rects.size(); i++)
+  {
+    mergingRect.Merge(rects[i]);
+  }
+}
+
+void insertRects(std::list<std::vector<Rect<int>>>& damagedRectsList, const std::vector<Rect<int>>& damagedRects)
+{
+  damagedRectsList.push_front(damagedRects);
+  if (damagedRectsList.size() > 4) // past triple buffers + current
+  {
+    damagedRectsList.pop_back();
+  }
+}
+
+void EglImplementation::SetDamage( EGLSurface& eglSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect )
+{
+  if (!mPartialUpdateRequired)
+  {
+    return;
+  }
+
+  if (eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context
+  {
+    EGLint width = 0;
+    EGLint height = 0;
+    eglQuerySurface(mEglDisplay, eglSurface, EGL_WIDTH, &width);
+    eglQuerySurface(mEglDisplay, eglSurface, EGL_HEIGHT, &height);
+    Rect<int> surfaceRect(0, 0, width, height);
+
+    mSurfaceRect = surfaceRect;
+
+    if (mFullSwapNextFrame)
+    {
+      mBufferAge = 0;
+      insertRects(mBufferDamagedRects, std::vector<Rect<int>>(1, surfaceRect));
+      clippingRect = Rect<int>();
+      return;
+    }
+
+    EGLint bufferAge = GetBufferAge(eglSurface);
+    if (mDamagedAreas.size())
+    {
+      mBufferAge = bufferAge;
+      if (bufferAge == 0)
+      {
+        // Buffer age is reset
+        clippingRect = Rect<int>();
+        return;
+      }
+
+      mergeRects(clippingRect, mDamagedAreas);
+    }
+    else
+    {
+      // Buffer age 0 means the back buffer in invalid and requires full swap
+      if (!damagedRects.size() || bufferAge != mBufferAge || bufferAge == 0)
+      {
+        // No damage or buffer is out of order or buffer age is reset
+        mBufferAge = bufferAge;
+        insertRects(mBufferDamagedRects, std::vector<Rect<int>>(1, surfaceRect));
+        clippingRect = Rect<int>();
+        return;
+      }
+
+      // We push current frame damaged rects here, zero index for current frame
+      mBufferAge = bufferAge;
+      insertRects(mBufferDamagedRects, damagedRects);
+
+      // Merge damaged rects into clipping rect
+      auto bufferDamagedRects = mBufferDamagedRects.begin();
+      while (bufferAge-- >= 0 && bufferDamagedRects != mBufferDamagedRects.end())
+      {
+        const std::vector<Rect<int>>& rects = *bufferDamagedRects++;
+        mergeRects(clippingRect, rects);
+      }
+    }
+
+    if (!clippingRect.Intersect(surfaceRect) || clippingRect.Area() > surfaceRect.Area() * 0.8)
+    {
+      // clipping area too big or doesn't intersect surface rect
+      clippingRect = Rect<int>();
+      return;
+    }
+
+    // DALI_LOG_ERROR("eglSetDamageRegionKHR(%d, %d, %d, %d)\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
+    EGLBoolean result = mEglSetDamageRegionKHR(mEglDisplay, eglSurface, reinterpret_cast<int*>(&clippingRect), 1);
+    if (result == EGL_FALSE)
+    {
+      DALI_LOG_ERROR("eglSetDamageRegionKHR(%d)\n", eglGetError());
+    }
+  }
+}
+
+void EglImplementation::SwapBuffers(EGLSurface& eglSurface, const std::vector<Rect<int>>& damagedRects)
+{
+  if (eglSurface != EGL_NO_SURFACE ) // skip if using surfaceless context
+  {
+    if (!mPartialUpdateRequired || mFullSwapNextFrame || mBufferAge == 0 || !damagedRects.size())
+    {
+      SwapBuffers(eglSurface);
+      return;
+    }
+
+#ifndef DALI_PROFILE_UBUNTU
+    if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT )
+    {
+      DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers started.\n" );
+    }
+#endif //DALI_PROFILE_UBUNTU
+
+    if (mDamagedAreas.size())
+    {
+      // DALI_LOG_ERROR("EglImplementation::SwapBuffers(%d)\n", mDamagedAreas.size());
+      EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast<int*>(mDamagedAreas.data()), mDamagedAreas.size());
+      if (result == EGL_FALSE)
+      {
+        DALI_LOG_ERROR("eglSwapBuffersWithDamageKHR(%d)\n", eglGetError());
+      }
+
+#ifndef DALI_PROFILE_UBUNTU
+      if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT )
+      {
+        DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers finished.\n" );
+        mSwapBufferCountAfterResume++;
+      }
+#endif //DALI_PROFILE_UBUNTU
+      return;
+    }
+
+    // current frame damaged rects were pushed by EglImplementation::SetDamage() to 0 index.
+    EGLint bufferAge = mBufferAge;
+    mCombinedDamagedRects.clear();
+
+    // Combine damaged rects from previous frames (beginning from bufferAge index) with the current frame (0 index)
+    auto bufferDamagedRects = mBufferDamagedRects.begin();
+    while (bufferAge-- >= 0 && bufferDamagedRects != mBufferDamagedRects.end())
+    {
+      const std::vector<Rect<int>>& rects = *bufferDamagedRects++;
+      mCombinedDamagedRects.insert(mCombinedDamagedRects.end(), rects.begin(), rects.end());
+    }
+
+    // Merge intersecting rects, form an array of non intersecting rects to help driver a bit
+    // Could be optional and can be removed, needs to be checked with and without on platform
+    const int n = mCombinedDamagedRects.size();
+    for (int i = 0; i < n-1; i++)
+    {
+      if (mCombinedDamagedRects[i].IsEmpty())
+      {
+        continue;
+      }
+
+      for (int j = i+1; j < n; j++)
+      {
+        if (mCombinedDamagedRects[j].IsEmpty())
+        {
+          continue;
+        }
+
+        if (mCombinedDamagedRects[i].Intersects(mCombinedDamagedRects[j]))
+        {
+          mCombinedDamagedRects[i].Merge(mCombinedDamagedRects[j]);
+          mCombinedDamagedRects[j].width = 0;
+          mCombinedDamagedRects[j].height = 0;
+        }
+      }
+    }
+
+    int j = 0;
+    for (int i = 0; i < n; i++)
+    {
+      if (!mCombinedDamagedRects[i].IsEmpty())
+      {
+        mCombinedDamagedRects[j++] = mCombinedDamagedRects[i];
+      }
+    }
+
+    if (j != 0)
+    {
+      mCombinedDamagedRects.resize(j);
+    }
+
+    if (!mCombinedDamagedRects.size() || (mCombinedDamagedRects[0].Area() > mSurfaceRect.Area() * 0.8))
+    {
+      SwapBuffers(eglSurface);
+      return;
+    }
+
+    // DALI_LOG_ERROR("EglImplementation::SwapBuffers(%d)\n", mCombinedDamagedRects.size());
+    EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast<int*>(mCombinedDamagedRects.data()), mCombinedDamagedRects.size());
+    if (result == EGL_FALSE)
+    {
+      DALI_LOG_ERROR("eglSwapBuffersWithDamageKHR(%d)\n", eglGetError());
+    }
 
 #ifndef DALI_PROFILE_UBUNTU
     if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT )
index efb9754..b505352 100644 (file)
  */
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/common/list-wrapper.h>
+#include <dali/public-api/common/vector-wrapper.h>
+
 #include <dali/internal/graphics/common/egl-include.h>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/math/rect.h>
 #include <dali/integration-api/core-enumerations.h>
 
 // INTERNAL INCLUDES
@@ -46,10 +50,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] partialUpdatedRequired Whether the partial update is required
    */
   EglImplementation( int multiSamplingLevel,
                      Integration::DepthBufferAvailable depthBufferRequired,
-                     Integration::StencilBufferAvailable stencilBufferRequired );
+                     Integration::StencilBufferAvailable stencilBufferRequired,
+                     Integration::PartialUpdateAvailable partialUpdateRequired );
 
   /**
    * Destructor
@@ -124,6 +130,36 @@ public:
   virtual void SwapBuffers( EGLSurface& eglSurface );
 
   /**
+   * Gets current back buffer age
+   */
+  EGLint GetBufferAge( EGLSurface& eglSurface ) const;
+
+  /**
+   * Gets if user set damaged areas
+   */
+  bool DamageAreasSet() const;
+
+  /**
+   * Sets damaged areas, overrides auto calculated ones
+   */
+  void SetDamageAreas( std::vector<Dali::Rect<int>>& damagedArea );
+
+  /**
+   * Forces full surface swap next frame, resets current partial update state.
+   */
+  void SetFullSwapNextFrame();
+
+  /**
+   * Performs an OpenGL set damage command with damaged rects
+   */
+  virtual void SetDamage( EGLSurface& eglSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect );
+
+  /**
+   * Performs an OpenGL swap buffers command with damaged rects
+   */
+  virtual void SwapBuffers( EGLSurface& eglSurface, const std::vector<Rect<int>>& damagedRects );
+
+  /**
    * Performs an OpenGL copy buffers command
    */
   virtual void CopyBuffers( EGLSurface& eglSurface );
@@ -246,10 +282,20 @@ private:
   bool                 mIsWindow;
   bool                 mDepthBufferRequired;
   bool                 mStencilBufferRequired;
+  bool                 mPartialUpdateRequired;
   bool                 mIsSurfacelessContextSupported;
   bool                 mIsKhrCreateContextSupported;
 
   uint32_t              mSwapBufferCountAfterResume;
+  PFNEGLSETDAMAGEREGIONKHRPROC mEglSetDamageRegionKHR;
+  PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC mEglSwapBuffersWithDamageKHR;
+
+  EGLint mBufferAge;
+  std::list<std::vector<Rect<int>>> mBufferDamagedRects;
+  std::vector<Rect<int>> mCombinedDamagedRects;
+  std::vector<Rect<int>> mDamagedAreas;
+  Rect<int> mSurfaceRect;
+  bool mFullSwapNextFrame;
 };
 
 } // namespace Adaptor
index 7fea428..1d00be7 100644 (file)
@@ -42,6 +42,7 @@ const unsigned int DEFAULT_STATISTICS_LOG_FREQUENCY = 2;
 const int DEFAULT_MULTI_SAMPLING_LEVEL = -1;
 const bool DEFAULT_DEPTH_BUFFER_REQUIRED_SETTING = true;
 const bool DEFAULT_STENCIL_BUFFER_REQUIRED_SETTING = true;
+const bool DEFAULT_PARTIAL_UPDATE_REQUIRED_SETTING = false;
 
 unsigned int GetIntegerEnvironmentVariable( const char* variable, unsigned int defaultValue )
 {
@@ -130,7 +131,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 ),
+  mPartialUpdateRequired( DEFAULT_PARTIAL_UPDATE_REQUIRED_SETTING )
 {
   ParseEnvironmentOptions();
 }
@@ -391,6 +393,11 @@ bool EnvironmentOptions::StencilBufferRequired() const
   return mStencilBufferRequired;
 }
 
+bool EnvironmentOptions::PartialUpdateRequired() const
+{
+  return mPartialUpdateRequired;
+}
+
 void EnvironmentOptions::ParseEnvironmentOptions()
 {
   // get logging options
@@ -660,6 +667,15 @@ void EnvironmentOptions::ParseEnvironmentOptions()
       mStencilBufferRequired = false;
     }
   }
+
+  int partialUpdateRequired( -1 );
+  if( GetIntegerEnvironmentVariable( DALI_ENV_ENABLE_PARTIAL_UPDATE, partialUpdateRequired ) )
+  {
+    if( partialUpdateRequired > 0 )
+    {
+      mPartialUpdateRequired = true;
+    }
+  }
 }
 
 } // Adaptor
index f72ebdd..4d4b458 100644 (file)
@@ -316,6 +316,11 @@ public:
    */
   bool StencilBufferRequired() const;
 
+  /**
+   * @return Whether the partial update is required.
+   */
+  bool PartialUpdateRequired() 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 mPartialUpdateRequired;                    ///< Whether the partial update is required
   std::unique_ptr<TraceManager> mTraceManager;    ///< TraceManager
 };
 
index ca1a9c8..1be9185 100644 (file)
@@ -128,6 +128,8 @@ namespace Adaptor
 
 #define DALI_ENV_DISABLE_STENCIL_BUFFER "DALI_DISABLE_STENCIL_BUFFER"
 
+#define DALI_ENV_ENABLE_PARTIAL_UPDATE "DALI_ENABLE_PARTIAL_UPDATE"
+
 #define DALI_ENV_WEB_ENGINE_NAME "DALI_WEB_ENGINE_NAME"
 
 #define DALI_ENV_DPI_HORIZONTAL "DALI_DPI_HORIZONTAL"
index b21ca77..15be716 100755 (executable)
@@ -32,6 +32,7 @@
 
 // INTERNAL HEADERS
 #include <dali/integration-api/adaptor-framework/render-surface-interface.h>
+#include <dali/internal/graphics/gles/egl-graphics.h>
 #include <dali/internal/window-system/common/event-handler.h>
 #include <dali/internal/window-system/common/orientation-impl.h>
 #include <dali/internal/window-system/common/render-surface-factory.h>
@@ -188,18 +189,42 @@ std::string Window::GetClassName() const
 void Window::Raise()
 {
   mWindowBase->Raise();
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
+
   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Raise() \n", this, mNativeWindowId );
 }
 
 void Window::Lower()
 {
   mWindowBase->Lower();
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
+
   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Lower() \n", this, mNativeWindowId );
 }
 
 void Window::Activate()
 {
   mWindowBase->Activate();
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
+
   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Activate() \n", this, mNativeWindowId );
 }
 
@@ -412,6 +437,13 @@ void Window::Show()
     mVisibilityChangedSignal.Emit( handle, true );
   }
 
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
+
   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Show(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible );
 }
 
@@ -430,6 +462,14 @@ void Window::Hide()
     mVisibilityChangedSignal.Emit( handle, false );
   }
 
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
+
   DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Hide(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible );
 }
 
@@ -478,6 +518,13 @@ void Window::SetInputRegion( const Rect< int >& inputRegion )
 {
   mWindowBase->SetInputRegion( inputRegion );
 
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
+
   DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::SetInputRegion: x = %d, y = %d, w = %d, h = %d\n", inputRegion.x, inputRegion.y, inputRegion.width, inputRegion.height );
 }
 
@@ -589,6 +636,13 @@ void Window::SetSize( Dali::Window::WindowSize size )
 
     mAdaptor->SurfaceResizeComplete( mSurface.get(), newSize );
   }
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
 }
 
 Dali::Window::WindowSize Window::GetSize() const
@@ -609,6 +663,13 @@ void Window::SetPosition( Dali::Window::WindowPosition position )
   PositionSize oldRect = mSurface->GetPositionSize();
 
   mWindowSurface->MoveResize( PositionSize( position.GetX(), position.GetY(), oldRect.width, oldRect.height ) );
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
 }
 
 Dali::Window::WindowPosition Window::GetPosition() const
@@ -647,6 +708,13 @@ void Window::SetPositionSize( PositionSize positionSize )
     mResizeSignal.Emit( handle, newSize );
     mAdaptor->SurfaceResizeComplete( mSurface.get(), newSize );
   }
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
 }
 
 Dali::Layer Window::GetRootLayer() const
@@ -711,6 +779,13 @@ void Window::OnIconifyChanged( bool iconified )
 
     DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Deiconified: visible = %d\n", this, mNativeWindowId, mVisible );
   }
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
 }
 
 void Window::OnFocusChanged( bool focusIn )
@@ -718,6 +793,13 @@ void Window::OnFocusChanged( bool focusIn )
   Dali::Window handle( this );
   mFocusChangedSignal.Emit( focusIn );
   mFocusChangeSignal.Emit( handle, focusIn );
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
 }
 
 void Window::OnOutputTransformed()
@@ -784,6 +866,13 @@ void Window::OnPause()
   {
     mEventHandler->Pause();
   }
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
 }
 
 void Window::OnResume()
@@ -792,6 +881,13 @@ void Window::OnResume()
   {
     mEventHandler->Resume();
   }
+
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetFullSwapNextFrame();
+  }
 }
 
 void Window::RecalculateTouchPosition( Integration::Point& point )
@@ -915,6 +1011,16 @@ int32_t Window::GetNativeId() const
   return mWindowBase->GetNativeWindowId();
 }
 
+void Window::SetDamagedAreas(std::vector<Dali::Rect<int>>& areas)
+{
+  GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface();
+  EglGraphics* eglGraphics = static_cast<EglGraphics*>(&graphics);
+  if (eglGraphics)
+  {
+    eglGraphics->SetDamagedAreas(areas);
+  }
+}
+
 } // Adaptor
 
 } // Internal
index ca1d3bf..3a877ae 100755 (executable)
@@ -359,6 +359,11 @@ public:
    */
   void SetAvailableOrientations( const Dali::Vector<Dali::Window::WindowOrientation>& orientations );
 
+  /**
+   * @copydoc Dali::DevelWindow::SetDamagedAreas()
+   */
+  void SetDamagedAreas(std::vector<Dali::Rect<int>>& areas);
+
 public: // Dali::Internal::Adaptor::SceneHolder
 
   /**
index c95d508..dfaefa4 100644 (file)
@@ -352,10 +352,12 @@ void WindowRenderSurface::StartRender()
 {
 }
 
-bool WindowRenderSurface::PreRender( bool resizingSurface )
+bool WindowRenderSurface::PreRender( bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect )
 {
   MakeContextCurrent();
 
+  auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
+
   if( resizingSurface )
   {
     // Window rotate or screen rotate
@@ -386,19 +388,24 @@ bool WindowRenderSurface::PreRender( bool resizingSurface )
 
       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" );
     }
+
+    if (eglGraphics)
+    {
+      Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+      eglImpl.SetFullSwapNextFrame();
+    }
   }
 
-  auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
-  if ( eglGraphics )
+  if (eglGraphics)
   {
-    GlImplementation& mGLES = eglGraphics->GetGlesInterface();
-    mGLES.PreRender();
+    Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+    eglImpl.SetDamage( mEGLSurface, damagedRects, clippingRect );
   }
 
   return true;
 }
 
-void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
+void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects )
 {
   // Inform the gl implementation that rendering has finished before informing the surface
   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
@@ -438,7 +445,7 @@ void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, b
     }
 
     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
-    eglImpl.SwapBuffers( mEGLSurface );
+    eglImpl.SwapBuffers( mEGLSurface, damagedRects );
 
     if( mRenderNotification )
     {
index f8160b8..bc03611 100644 (file)
@@ -156,12 +156,12 @@ public: // from Dali::RenderSurfaceInterface
   /**
    * @copydoc Dali::RenderSurfaceInterface::PreRender()
    */
-  virtual bool PreRender( bool resizingSurface ) override;
+  virtual bool PreRender( bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect ) override;
 
   /**
    * @copydoc Dali::RenderSurfaceInterface::PostRender()
    */
-  virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface );
+  virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects ) override;
 
   /**
    * @copydoc Dali::RenderSurfaceInterface::StopRender()
index 3ef4f68..48069c7 100644 (file)
@@ -216,20 +216,30 @@ void NativeRenderSurfaceEcoreWl::StartRender()
 {
 }
 
-bool NativeRenderSurfaceEcoreWl::PreRender( bool )
+bool NativeRenderSurfaceEcoreWl::PreRender( bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect )
 {
-  // nothing to do for pixmaps
+  auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics*>(mGraphics);
+  if (eglGraphics)
+  {
+    Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
+    if (resizingSurface)
+    {
+      eglImpl.SetFullSwapNextFrame();
+    }
+
+    eglImpl.SetDamage(mEGLSurface, damagedRects, clippingRect);
+  }
+
   return true;
 }
 
-void NativeRenderSurfaceEcoreWl::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
+void NativeRenderSurfaceEcoreWl::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects )
 {
   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics *>(mGraphics);
-  if ( eglGraphics )
+  if (eglGraphics)
   {
     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
-
-    eglImpl.SwapBuffers( mEGLSurface );
+    eglImpl.SwapBuffers( mEGLSurface, damagedRects );
   }
 
   if( mThreadSynchronization )
index e3a33ba..bfca63c 100644 (file)
@@ -116,12 +116,12 @@ public: // from Dali::RenderSurfaceInterface
   /**
    * @copydoc Dali::RenderSurfaceInterface::PreRender()
    */
-  virtual bool PreRender( bool resizingSurface ) override;
+  virtual bool PreRender( bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect ) override;
 
   /**
    * @copydoc Dali::RenderSurfaceInterface::PostRender()
    */
-  virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface );
+  virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects ) override;
 
   /**
    * @copydoc Dali::RenderSurfaceInterface::StopRender()
index 2e93140..527f5cc 100644 (file)
@@ -220,13 +220,13 @@ void PixmapRenderSurfaceEcoreX::StartRender()
 {
 }
 
-bool PixmapRenderSurfaceEcoreX::PreRender( bool )
+bool PixmapRenderSurfaceEcoreX::PreRender( bool, const std::vector<Rect<int>>&, Rect<int>& )
 {
   // Nothing to do for pixmaps
   return true;
 }
 
-void PixmapRenderSurfaceEcoreX::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
+void PixmapRenderSurfaceEcoreX::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects )
 {
   auto eglGraphics = static_cast<EglGraphics *>(mGraphics);
 
index 034fee6..ebedfef 100644 (file)
@@ -114,12 +114,12 @@ public: // from Dali::RenderSurfaceInterface
   /**
    * @copydoc Dali::RenderSurfaceInterface::PreRender()
    */
-  virtual bool PreRender( bool resizingSurface ) override;
+  virtual bool PreRender( bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect ) override;
 
   /**
    * @copydoc Dali::RenderSurfaceInterface::PostRender()
    */
-  virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ) override;
+  virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects ) override;
 
   /**
    * @copydoc Dali::RenderSurfaceInterface::StopRender()