X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fwindow-system%2Fcommon%2Fwindow-render-surface.cpp;h=8a066b00874b7e4b1d824a951c489a6eb144ae9b;hb=2954c0a2cc2efae61afd86822e63532d4dd8ae7d;hp=73260472ca3910196d3cf86fb506dcc0845b2946;hpb=2ed7f63e95a2a88742561910d39da6206c786dc6;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git diff --git a/dali/internal/window-system/common/window-render-surface.cpp b/dali/internal/window-system/common/window-render-surface.cpp index 7326047..8a066b0 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 ); @@ -107,13 +139,6 @@ void WindowRenderSurface::Initialize( Any surface ) // Connect signals mWindowBase->OutputTransformedSignal().Connect( this, &WindowRenderSurface::OutputTransformed ); - - // Check screen rotation - mScreenRotationAngle = mWindowBase->GetScreenRotationAngle(); - if( mScreenRotationAngle != 0 ) - { - mScreenRotationFinished = false; - } } Any WindowRenderSurface::GetNativeWindow() @@ -143,12 +168,6 @@ void WindowRenderSurface::SetTransparency( bool transparent ) void WindowRenderSurface::RequestRotation( int angle, int width, int height ) { - if( !mRotationSupported ) - { - DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::Rotate: Rotation is not supported!\n" ); - return; - } - if( !mRotationTrigger ) { mRotationTrigger = TriggerEventFactory::CreateTriggerEvent( MakeCallback( this, &WindowRenderSurface::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER ); @@ -200,6 +219,11 @@ void WindowRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpi dpiVertical = mDpiVertical; } +int WindowRenderSurface::GetOrientation() const +{ + return mWindowBase->GetOrientation(); +} + void WindowRenderSurface::InitializeGraphics() { mGraphics = &mAdaptor->GetGraphicsInterface(); @@ -225,20 +249,8 @@ void WindowRenderSurface::CreateSurface() { DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter ); - int width, height; - if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 ) - { - width = mPositionSize.width; - height = mPositionSize.height; - } - else - { - width = mPositionSize.height; - height = mPositionSize.width; - } - // Create the EGL window - EGLNativeWindowType window = mWindowBase->CreateEglWindow( width, height ); + EGLNativeWindowType window = mWindowBase->CreateEglWindow( mPositionSize.width, mPositionSize.height ); auto eglGraphics = static_cast(mGraphics); @@ -423,15 +435,13 @@ bool WindowRenderSurface::PreRender( bool resizingSurface, const std::vector(mGraphics); - if( resizingSurface ) { + int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360; + // Window rotate or screen rotate if( !mRotationFinished || !mScreenRotationFinished ) { - int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360; - mWindowBase->SetEglWindowRotation( totalAngle ); mWindowBase->SetEglWindowBufferTransform( totalAngle ); @@ -448,26 +458,31 @@ bool WindowRenderSurface::PreRender( bool resizingSurface, const std::vectorResizeEglWindow( mPositionSize ); + Dali::PositionSize positionSize; + positionSize.x = mPositionSize.x; + positionSize.y = mPositionSize.y; + if( totalAngle == 0 || totalAngle == 180 ) + { + positionSize.width = mPositionSize.width; + positionSize.height = mPositionSize.height; + } + else + { + positionSize.width = mPositionSize.height; + positionSize.height = mPositionSize.width; + } + mWindowBase->ResizeEglWindow( positionSize ); mResizeFinished = true; DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::PreRender: Set resize\n" ); } - if (eglGraphics) - { - Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); - eglImpl.SetFullSwapNextFrame(); - } + SetFullSwapNextFrame(); } - if (eglGraphics) - { - Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); - eglImpl.SetDamage( mEGLSurface, damagedRects, clippingRect ); - } + SetBufferDamagedRects( damagedRects, clippingRect ); return true; } @@ -511,8 +526,7 @@ void WindowRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, b } } - Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation(); - eglImpl.SwapBuffers( mEGLSurface, damagedRects ); + SwapBuffers( damagedRects ); if( mRenderNotification ) { @@ -568,14 +582,15 @@ void WindowRenderSurface::OutputTransformed() { mScreenRotationAngle = screenRotationAngle; mScreenRotationFinished = false; + mResizeFinished = false; mOutputTransformedSignal.Emit(); - DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle ); + DALI_LOG_RELEASE_INFO( "WindowRenderSurface::OutputTransformed: window = %d screen = %d\n", mRotationAngle, mScreenRotationAngle ); } else { - DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle ); + DALI_LOG_RELEASE_INFO( "WindowRenderSurface::OutputTransformed: Ignore output transform [%d]\n", mScreenRotationAngle ); } } @@ -646,6 +661,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