From b04f674185b7ce6981eff913efcea029f542763c Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Fri, 21 Aug 2020 18:02:30 +0900 Subject: [PATCH] Support multiple surfaces for partial update Change-Id: I0880ce461407c48bc0290f73fd1bc8824f5e46a8 --- .../adaptor-framework/render-surface-interface.h | 10 ++ .../adaptor-framework/scene-holder-impl.cpp | 14 +- dali/internal/graphics/gles/egl-graphics.cpp | 5 - dali/internal/graphics/gles/egl-graphics.h | 5 - dali/internal/graphics/gles/egl-implementation.cpp | 151 ++--------------- dali/internal/graphics/gles/egl-implementation.h | 16 +- dali/internal/window-system/common/window-impl.cpp | 92 ++--------- .../window-system/common/window-render-surface.cpp | 181 +++++++++++++++++++-- .../window-system/common/window-render-surface.h | 22 ++- .../native-render-surface-ecore-wl.cpp | 13 +- 10 files changed, 225 insertions(+), 284 deletions(-) diff --git a/dali/integration-api/adaptor-framework/render-surface-interface.h b/dali/integration-api/adaptor-framework/render-surface-interface.h index 2c7f6b7..2014e89 100644 --- a/dali/integration-api/adaptor-framework/render-surface-interface.h +++ b/dali/integration-api/adaptor-framework/render-surface-interface.h @@ -82,6 +82,7 @@ public: mGraphics( nullptr ), mDisplayConnection( nullptr ), mScene(), + mFullSwapNextFrame( true ), mDepthBufferRequired( Integration::DepthBufferAvailable::FALSE ), mStencilBufferRequired( Integration::StencilBufferAvailable::FALSE ) {} @@ -220,6 +221,14 @@ public: mScene = scene; } + /** + * @brief Forces full surface swap next frame, resets current partial update state. + */ + void SetFullSwapNextFrame() + { + mFullSwapNextFrame = true; + } + private: /** @@ -238,6 +247,7 @@ protected: Dali::Internal::Adaptor::GraphicsInterface* mGraphics; Dali::DisplayConnection* mDisplayConnection; WeakHandle< Dali::Integration::Scene > mScene; + bool mFullSwapNextFrame; ///< Whether the full surface swap is required private: diff --git a/dali/integration-api/adaptor-framework/scene-holder-impl.cpp b/dali/integration-api/adaptor-framework/scene-holder-impl.cpp index e545376..69ce19e 100644 --- a/dali/integration-api/adaptor-framework/scene-holder-impl.cpp +++ b/dali/integration-api/adaptor-framework/scene-holder-impl.cpp @@ -214,12 +214,7 @@ void SceneHolder::SurfaceResized() PositionSize surfacePositionSize = mSurface->GetPositionSize(); mScene.SurfaceResized( static_cast( surfacePositionSize.width ), static_cast( surfacePositionSize.height ) ); - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); } Dali::RenderSurfaceInterface* SceneHolder::GetSurface() const @@ -233,12 +228,7 @@ void SceneHolder::SetBackgroundColor( const Vector4& color ) { mScene.SetBackgroundColor( color ); - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); } } diff --git a/dali/internal/graphics/gles/egl-graphics.cpp b/dali/internal/graphics/gles/egl-graphics.cpp index a30abd3..dcbf055 100644 --- a/dali/internal/graphics/gles/egl-graphics.cpp +++ b/dali/internal/graphics/gles/egl-graphics.cpp @@ -129,11 +129,6 @@ EglImageExtensions* EglGraphics::GetImageExtensions() return mEglImageExtensions.get(); } -void EglGraphics::SetFullSwapNextFrame() -{ - mEglImplementation->SetFullSwapNextFrame(); -} - } // Adaptor } // Internal } // Dali diff --git a/dali/internal/graphics/gles/egl-graphics.h b/dali/internal/graphics/gles/egl-graphics.h index 5ddfbfb..8ee45bc 100644 --- a/dali/internal/graphics/gles/egl-graphics.h +++ b/dali/internal/graphics/gles/egl-graphics.h @@ -126,11 +126,6 @@ public: EglImageExtensions* GetImageExtensions(); /** - * 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; diff --git a/dali/internal/graphics/gles/egl-implementation.cpp b/dali/internal/graphics/gles/egl-implementation.cpp index 6e39644..d674055 100755 --- a/dali/internal/graphics/gles/egl-implementation.cpp +++ b/dali/internal/graphics/gles/egl-implementation.cpp @@ -87,8 +87,7 @@ EglImplementation::EglImplementation( int multiSamplingLevel, mIsKhrCreateContextSupported( false ), mSwapBufferCountAfterResume( 0 ), mEglSetDamageRegionKHR( 0 ), - mEglSwapBuffersWithDamageKHR( 0 ), - mFullSwapNextFrame( true ) + mEglSwapBuffersWithDamageKHR( 0 ) { } @@ -360,7 +359,6 @@ void EglImplementation::SwapBuffers( EGLSurface& eglSurface ) // DALI_LOG_ERROR("EglImplementation::SwapBuffers()\n"); eglSwapBuffers( mEglDisplay, eglSurface ); - mFullSwapNextFrame = false; #ifndef DALI_PROFILE_UBUNTU if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT ) @@ -393,99 +391,19 @@ EGLint EglImplementation::GetBufferAge(EGLSurface& eglSurface) const return age; } -void EglImplementation::SetFullSwapNextFrame() +void EglImplementation::SetDamageRegion( EGLSurface& eglSurface, std::vector< Rect< int > >& damagedRects ) { - mFullSwapNextFrame = true; -} - -void mergeRects(Rect& mergingRect, const std::vector>& 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>>& damagedRectsList, const std::vector>& damagedRects) -{ - damagedRectsList.push_front(damagedRects); - if (damagedRectsList.size() > 4) // past triple buffers + current - { - damagedRectsList.pop_back(); - } -} - -void EglImplementation::SetDamage( EGLSurface& eglSurface, const std::vector>& damagedRects, Rect& clippingRect ) -{ - if (!mPartialUpdateRequired) + if( !mPartialUpdateRequired ) { return; } - if (eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context + 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 surfaceRect(0, 0, width, height); - - mSurfaceRect = surfaceRect; - - if (mFullSwapNextFrame) - { - insertRects(mBufferDamagedRects, std::vector>(1, surfaceRect)); - clippingRect = Rect(); - return; - } - - EGLint bufferAge = GetBufferAge(eglSurface); - - // Buffer age 0 means the back buffer in invalid and requires full swap - if (!damagedRects.size() || bufferAge == 0) - { - // No damage or buffer is out of order or buffer age is reset - insertRects(mBufferDamagedRects, std::vector>(1, surfaceRect)); - clippingRect = Rect(); - return; - } - - // We push current frame damaged rects here, zero index for current frame - insertRects(mBufferDamagedRects, damagedRects); - - // Merge damaged rects into clipping rect - auto bufferDamagedRects = mBufferDamagedRects.begin(); - while (bufferAge-- >= 0 && bufferDamagedRects != mBufferDamagedRects.end()) - { - const std::vector>& 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(); - 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(&clippingRect), 1); + EGLBoolean result = mEglSetDamageRegionKHR( mEglDisplay, eglSurface, reinterpret_cast< int* >( damagedRects.data() ), 1 ); if (result == EGL_FALSE) { - DALI_LOG_ERROR("eglSetDamageRegionKHR(%d)\n", eglGetError()); + DALI_LOG_ERROR( "eglSetDamageRegionKHR(%d)\n", eglGetError() ); } } } @@ -494,7 +412,7 @@ void EglImplementation::SwapBuffers(EGLSurface& eglSurface, const std::vector mSurfaceRect.Area() * 0.8) ) + if (!mPartialUpdateRequired ) { SwapBuffers(eglSurface); return; @@ -507,55 +425,7 @@ void EglImplementation::SwapBuffers(EGLSurface& eglSurface, const std::vector > mergedRects = damagedRects; - - // 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 = mergedRects.size(); - for(int i = 0; i < n-1; i++) - { - if (mergedRects[i].IsEmpty()) - { - continue; - } - - for (int j = i+1; j < n; j++) - { - if (mergedRects[j].IsEmpty()) - { - continue; - } - - if (mergedRects[i].Intersects(mergedRects[j])) - { - mergedRects[i].Merge(mergedRects[j]); - mergedRects[j].width = 0; - mergedRects[j].height = 0; - } - } - } - - int j = 0; - for (int i = 0; i < n; i++) - { - if (!mergedRects[i].IsEmpty()) - { - mergedRects[j++] = mergedRects[i]; - } - } - - if (j != 0) - { - mergedRects.resize(j); - } - - if (!mergedRects.size() || (mergedRects[0].Area() > mSurfaceRect.Area() * 0.8)) - { - SwapBuffers(eglSurface); - return; - } - - EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast(mergedRects.data()), mergedRects.size()); + EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast(const_cast< std::vector< Rect< int > >& >( damagedRects ).data()), damagedRects.size()); if (result == EGL_FALSE) { DALI_LOG_ERROR("eglSwapBuffersWithDamageKHR(%d)\n", eglGetError()); @@ -830,6 +700,11 @@ void EglImplementation::WaitClient() } } +bool EglImplementation::IsPartialUpdateRequired() const +{ + return mPartialUpdateRequired; +} + } // namespace Adaptor } // namespace Internal diff --git a/dali/internal/graphics/gles/egl-implementation.h b/dali/internal/graphics/gles/egl-implementation.h index 73d11bb..34d0f5c 100644 --- a/dali/internal/graphics/gles/egl-implementation.h +++ b/dali/internal/graphics/gles/egl-implementation.h @@ -135,14 +135,9 @@ public: EGLint GetBufferAge( EGLSurface& eglSurface ) const; /** - * 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>& damagedRects, Rect& clippingRect ); + void SetDamageRegion( EGLSurface& eglSurface, std::vector< Rect< int > >& damagedRects ); /** * Performs an OpenGL swap buffers command with damaged rects @@ -239,6 +234,12 @@ public: */ void WaitClient(); + /** + * @brief Returns whether the partial update is required. + * @return true if the partial update is required. + */ + bool IsPartialUpdateRequired() const; + private: Vector mContextAttribs; @@ -280,9 +281,6 @@ private: PFNEGLSETDAMAGEREGIONKHRPROC mEglSetDamageRegionKHR; PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC mEglSwapBuffersWithDamageKHR; - std::list>> mBufferDamagedRects; - Rect mSurfaceRect; - bool mFullSwapNextFrame; }; } // namespace Adaptor diff --git a/dali/internal/window-system/common/window-impl.cpp b/dali/internal/window-system/common/window-impl.cpp index be1c3ad..a224207 100755 --- a/dali/internal/window-system/common/window-impl.cpp +++ b/dali/internal/window-system/common/window-impl.cpp @@ -178,12 +178,7 @@ void Window::Raise() { mWindowBase->Raise(); - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Raise() \n", this, mNativeWindowId ); } @@ -192,12 +187,7 @@ void Window::Lower() { mWindowBase->Lower(); - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Lower() \n", this, mNativeWindowId ); } @@ -206,12 +196,7 @@ void Window::Activate() { mWindowBase->Activate(); - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Activate() \n", this, mNativeWindowId ); } @@ -425,12 +410,7 @@ void Window::Show() mVisibilityChangedSignal.Emit( handle, true ); } - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Show(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible ); } @@ -450,14 +430,6 @@ void Window::Hide() mVisibilityChangedSignal.Emit( handle, false ); } - - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } - DALI_LOG_RELEASE_INFO( "Window (%p), WinId (%d), Hide(): iconified = %d, visible = %d\n", this, mNativeWindowId, mIconified, mVisible ); } @@ -506,13 +478,6 @@ void Window::SetInputRegion( const Rect< int >& inputRegion ) { mWindowBase->SetInputRegion( inputRegion ); - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&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 ); } @@ -624,12 +589,7 @@ void Window::SetSize( Dali::Window::WindowSize size ) mAdaptor->SurfaceResizeComplete( mSurface.get(), newSize ); } - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); } Dali::Window::WindowSize Window::GetSize() const @@ -651,12 +611,7 @@ void Window::SetPosition( Dali::Window::WindowPosition position ) mWindowSurface->MoveResize( PositionSize( position.GetX(), position.GetY(), oldRect.width, oldRect.height ) ); - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); } Dali::Window::WindowPosition Window::GetPosition() const @@ -695,12 +650,7 @@ void Window::SetPositionSize( PositionSize positionSize ) mAdaptor->SurfaceResizeComplete( mSurface.get(), newSize ); } - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); } Dali::Layer Window::GetRootLayer() const @@ -766,12 +716,7 @@ 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(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); } void Window::OnFocusChanged( bool focusIn ) @@ -779,12 +724,7 @@ void Window::OnFocusChanged( bool focusIn ) Dali::Window handle( this ); mFocusChangeSignal.Emit( handle, focusIn ); - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); } void Window::OnOutputTransformed() @@ -856,13 +796,6 @@ void Window::OnPause() { mEventHandler->Pause(); } - - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } } void Window::OnResume() @@ -872,12 +805,7 @@ void Window::OnResume() mEventHandler->Resume(); } - GraphicsInterface& graphics = mAdaptor->GetGraphicsInterface(); - EglGraphics* eglGraphics = static_cast(&graphics); - if (eglGraphics) - { - eglGraphics->SetFullSwapNextFrame(); - } + mSurface->SetFullSwapNextFrame(); } void Window::RecalculateTouchPosition( Integration::Point& point ) diff --git a/dali/internal/window-system/common/window-render-surface.cpp b/dali/internal/window-system/common/window-render-surface.cpp index 7326047..021843e 100644 --- a/dali/internal/window-system/common/window-render-surface.cpp +++ b/dali/internal/window-system/common/window-render-surface.cpp @@ -45,11 +45,42 @@ namespace { const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved +const float FULL_UPDATE_RATIO( 0.8f ); ///< Force full update when the dirty area is larget than this ratio #if defined(DEBUG_ENABLED) Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE"); #endif +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( WindowRenderSurface::DamagedRectsContainer& damagedRectsList, const std::vector< Rect< int > >& damagedRects ) +{ + damagedRectsList.push_front( damagedRects ); + if( damagedRectsList.size() > 4 ) // past triple buffers + current + { + damagedRectsList.pop_back(); + } +} + } // unnamed namespace WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any surface, bool isTransparent ) @@ -67,16 +98,17 @@ WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize, Any s mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ), mOutputTransformedSignal(), mFrameCallbackInfoContainer(), + mBufferDamagedRects(), mMutex(), mRotationAngle( 0 ), mScreenRotationAngle( 0 ), + mDpiHorizontal( 0 ), + mDpiVertical( 0 ), mOwnSurface( false ), mRotationSupported( false ), mRotationFinished( true ), mScreenRotationFinished( true ), - mResizeFinished( true ), - mDpiHorizontal( 0 ), - mDpiVertical( 0 ) + mResizeFinished( true ) { DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" ); Initialize( surface ); @@ -423,8 +455,6 @@ bool WindowRenderSurface::PreRender( bool resizingSurface, const std::vector(mGraphics); - if( resizingSurface ) { // Window rotate or screen rotate @@ -456,18 +486,10 @@ bool WindowRenderSurface::PreRender( bool resizingSurface, const std::vectorGetEglImplementation(); - eglImpl.SetFullSwapNextFrame(); - } + SetFullSwapNextFrame(); } - if (eglGraphics) - { - Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); - eglImpl.SetDamage( mEGLSurface, damagedRects, clippingRect ); - } + SetBufferDamagedRects( damagedRects, clippingRect ); return true; } @@ -511,8 +533,7 @@ void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, b } } - Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); - eglImpl.SwapBuffers( mEGLSurface, damagedRects ); + SwapBuffers( damagedRects ); if( mRenderNotification ) { @@ -646,6 +667,132 @@ void WindowRenderSurface::OnFileDescriptorEventDispatched( FileDescriptorMonitor } } +void WindowRenderSurface::SetBufferDamagedRects( const std::vector< Rect< int > >& damagedRects, Rect< int >& clippingRect ) +{ + auto eglGraphics = static_cast< EglGraphics* >( mGraphics ); + if ( eglGraphics ) + { + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + if( !eglImpl.IsPartialUpdateRequired() ) + { + return; + } + + Rect< int > surfaceRect( 0, 0, mPositionSize.width, mPositionSize.height ); + + if( mFullSwapNextFrame ) + { + InsertRects( mBufferDamagedRects, std::vector< Rect< int > >( 1, surfaceRect ) ); + clippingRect = Rect< int >(); + return; + } + + EGLint bufferAge = eglImpl.GetBufferAge( mEGLSurface ); + + // Buffer age 0 means the back buffer in invalid and requires full swap + if( !damagedRects.size() || bufferAge == 0 ) + { + InsertRects( mBufferDamagedRects, std::vector< Rect< int > >( 1, surfaceRect ) ); + clippingRect = Rect< int >(); + return; + } + + // We push current frame damaged rects here, zero index for current frame + 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() * FULL_UPDATE_RATIO ) + { + // clipping area too big or doesn't intersect surface rect + clippingRect = Rect< int >(); + return; + } + + std::vector< Rect< int > > damagedRegion; + damagedRegion.push_back( clippingRect ); + + eglImpl.SetDamageRegion( mEGLSurface, damagedRegion ); + } +} + +void WindowRenderSurface::SwapBuffers( const std::vector>& damagedRects ) +{ + auto eglGraphics = static_cast< EglGraphics* >( mGraphics ); + if( eglGraphics ) + { + Rect< int > surfaceRect( 0, 0, mPositionSize.width, mPositionSize.height ); + + Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); + + if( !eglImpl.IsPartialUpdateRequired() || mFullSwapNextFrame || !damagedRects.size() || (damagedRects[0].Area() > surfaceRect.Area() * FULL_UPDATE_RATIO) ) + { + mFullSwapNextFrame = false; + eglImpl.SwapBuffers( mEGLSurface ); + return; + } + + mFullSwapNextFrame = false; + + std::vector< Rect< int > > mergedRects = damagedRects; + + // 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 = mergedRects.size(); + for( int i = 0; i < n - 1; i++ ) + { + if( mergedRects[i].IsEmpty() ) + { + continue; + } + + for( int j = i + 1; j < n; j++ ) + { + if( mergedRects[j].IsEmpty() ) + { + continue; + } + + if( mergedRects[i].Intersects( mergedRects[j] ) ) + { + mergedRects[i].Merge( mergedRects[j] ); + mergedRects[j].width = 0; + mergedRects[j].height = 0; + } + } + } + + int j = 0; + for( int i = 0; i < n; i++ ) + { + if( !mergedRects[i].IsEmpty() ) + { + mergedRects[j++] = mergedRects[i]; + } + } + + if( j != 0 ) + { + mergedRects.resize( j ); + } + + if( !mergedRects.size() || ( mergedRects[0].Area() > surfaceRect.Area() * FULL_UPDATE_RATIO ) ) + { + eglImpl.SwapBuffers( mEGLSurface ); + } + else + { + eglImpl.SwapBuffers( mEGLSurface, mergedRects ); + } + } +} + } // namespace Adaptor } // namespace internal diff --git a/dali/internal/window-system/common/window-render-surface.h b/dali/internal/window-system/common/window-render-surface.h index 6b72a55..faf8f50 100644 --- a/dali/internal/window-system/common/window-render-surface.h +++ b/dali/internal/window-system/common/window-render-surface.h @@ -51,7 +51,8 @@ class WindowRenderSurface : public Dali::RenderSurfaceInterface, public Connecti { public: - typedef Signal< void ( ) > OutputSignalType; + using OutputSignalType = Signal< void ( ) >; + using DamagedRectsContainer = std::list< std::vector< Rect< int > > >; /** * Uses an window surface to render to. @@ -231,6 +232,19 @@ private: */ void OnFileDescriptorEventDispatched( FileDescriptorMonitor::EventType eventBitMask, int fileDescriptor ); + /** + * @brief Set the buffer damage rects. + * @param[in] damagedRects List of damaged rects + * @param[in] clippingRect The rect to clip rendered scene + */ + void SetBufferDamagedRects( const std::vector< Rect< int > >& damagedRects, Rect< int >& clippingRect ); + + /** + * @brief Swap buffers. + * @param[in] damagedRects List of damaged rects + */ + void SwapBuffers( const std::vector>& damagedRects ); + protected: // Undefined @@ -285,18 +299,18 @@ private: // Data ColorDepth mColorDepth; ///< Color depth of surface (32 bit or 24 bit) OutputSignalType mOutputTransformedSignal; FrameCallbackInfoContainer mFrameCallbackInfoContainer; + DamagedRectsContainer mBufferDamagedRects; Dali::Mutex mMutex; int mRotationAngle; int mScreenRotationAngle; + uint32_t mDpiHorizontal; + uint32_t mDpiVertical; bool mOwnSurface; ///< Whether we own the surface (responsible for deleting it) bool mRotationSupported; bool mRotationFinished; bool mScreenRotationFinished; bool mResizeFinished; - uint32_t mDpiHorizontal; - uint32_t mDpiVertical; - }; // class WindowRenderSurface } // namespace Adaptor diff --git a/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp b/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp index 7ade18f..2aaa623 100644 --- a/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp +++ b/dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp @@ -226,18 +226,7 @@ void NativeRenderSurfaceEcoreWl::StartRender() bool NativeRenderSurfaceEcoreWl::PreRender( bool resizingSurface, const std::vector>& damagedRects, Rect& clippingRect ) { - auto eglGraphics = static_cast(mGraphics); - if (eglGraphics) - { - Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); - if (resizingSurface) - { - eglImpl.SetFullSwapNextFrame(); - } - - eglImpl.SetDamage(mEGLSurface, damagedRects, clippingRect); - } - + //TODO: Need to support partial update return true; } -- 2.7.4