X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-core.git;a=blobdiff_plain;f=dali%2Finternal%2Frender%2Fcommon%2Frender-manager.cpp;h=986e430cedba0e405d355202231828e4bbada283;hp=d9c2ea0102c0eee7278f28b0866fbb754a546fea;hb=b43741a90b40ca9dfbd33d6a9d390d3c09230e89;hpb=75552e8d3b4e8db822723d0c177afe1becc4b4cc diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp old mode 100644 new mode 100755 index d9c2ea0..986e430 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -62,6 +62,37 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_REN } // unnamed namespace #endif +namespace +{ +const float partialUpdateRatio = 0.8f; // If the partial update area exceeds 80%, change to full update. + +/** + * @brief Find the intersection of two AABB rectangles. + * This is a logical AND operation. IE. The intersection is the area overlapped by both rectangles. + * @param[in] aabbA Rectangle A + * @param[in] aabbB Rectangle B + * @return The intersection of rectangle A & B (result is a rectangle) + */ +inline ClippingBox IntersectAABB( const ClippingBox& aabbA, const ClippingBox& aabbB ) +{ + ClippingBox intersectionBox; + + // First calculate the largest starting positions in X and Y. + intersectionBox.x = std::max( aabbA.x, aabbB.x ); + intersectionBox.y = std::max( aabbA.y, aabbB.y ); + + // Now calculate the smallest ending positions, and take the largest starting + // positions from the result, to get the width and height respectively. + // If the two boxes do not intersect at all, then we need a 0 width and height clipping area. + // We use max here to clamp both width and height to >= 0 for this use-case. + intersectionBox.width = std::max( std::min( aabbA.x + aabbA.width, aabbB.x + aabbB.width ) - intersectionBox.x, 0 ); + intersectionBox.height = std::max( std::min( aabbA.y + aabbA.height, aabbB.y + aabbB.height ) - intersectionBox.y, 0 ); + + return intersectionBox; +} + +} + /** * Structure to contain internal data */ @@ -71,7 +102,8 @@ struct RenderManager::Impl Integration::GlSyncAbstraction& glSyncAbstraction, Integration::GlContextHelperAbstraction& glContextHelperAbstraction, Integration::DepthBufferAvailable depthBufferAvailableParam, - Integration::StencilBufferAvailable stencilBufferAvailableParam ) + Integration::StencilBufferAvailable stencilBufferAvailableParam, + Integration::PartialUpdateAvailable partialUpdateAvailableParam ) : context( glAbstraction, &surfaceContextContainer ), currentContext( &context ), glAbstraction( glAbstraction ), @@ -92,6 +124,7 @@ struct RenderManager::Impl programController( glAbstraction ), depthBufferAvailable( depthBufferAvailableParam ), stencilBufferAvailable( stencilBufferAvailableParam ), + partialUpdateAvailable( partialUpdateAvailableParam ), defaultSurfaceOrientation( 0 ) { // Create thread pool with just one thread ( there may be a need to create more threads in the future ). @@ -171,6 +204,7 @@ struct RenderManager::Impl Integration::DepthBufferAvailable depthBufferAvailable; ///< Whether the depth buffer is available Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available + Integration::PartialUpdateAvailable partialUpdateAvailable; ///< Whether the partial update is available std::unique_ptr threadPool; ///< The thread pool Vector boundTextures; ///< The textures bound for rendering @@ -183,14 +217,16 @@ RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction, Integration::GlSyncAbstraction& glSyncAbstraction, Integration::GlContextHelperAbstraction& glContextHelperAbstraction, Integration::DepthBufferAvailable depthBufferAvailable, - Integration::StencilBufferAvailable stencilBufferAvailable ) + Integration::StencilBufferAvailable stencilBufferAvailable, + Integration::PartialUpdateAvailable partialUpdateAvailable ) { RenderManager* manager = new RenderManager; manager->mImpl = new Impl( glAbstraction, glSyncAbstraction, glContextHelperAbstraction, depthBufferAvailable, - stencilBufferAvailable ); + stencilBufferAvailable, + partialUpdateAvailable ); return manager; } @@ -592,10 +628,87 @@ void RenderManager::Render( Integration::RenderStatus& status, bool forceClear ) DALI_PRINT_RENDER_END(); } +bool GetDamagedRect( Rect &viewportRect, RenderInstruction& instruction, Rect &damagedRect ) +{ + // merge bounding + int dx1 = viewportRect.width, dx2 = 0, dy1 = viewportRect.height, dy2 = 0; + int checkWidth = static_cast( static_cast( viewportRect.width ) * partialUpdateRatio ); + int checkHeight = static_cast( static_cast( viewportRect.height ) * partialUpdateRatio ); + Rect screenRect; + + bool isPartialUpdate = false; + + const RenderListContainer::SizeType renderListCount = instruction.RenderListCount(); + // Iterate through each render list. + + for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index ) + { + const RenderList* renderList = instruction.GetRenderList( index ); + + if( renderList && !renderList->IsEmpty() && renderList->IsPartialUpdateEnabled() ) + { + const std::size_t itemCount = renderList->Count(); + for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex ) + { + const RenderItem& item = renderList->GetItem( itemIndex ); + + if( item.mPartialUpdateEnabled ) + { + isPartialUpdate = true; + + screenRect = item.CalculateViewportSpaceAABB( viewportRect.width, viewportRect.height, true ); + + dx1 = std::min( screenRect.x, dx1 ); + dx2 = std::max( screenRect.x + screenRect.width, dx2); + dy1 = std::min( screenRect.y, dy1 ); + dy2 = std::max( screenRect.y + screenRect.height, dy2 ); + + if( ( dx2 - dx1 ) > checkWidth && ( dy2 - dy1 ) > checkHeight ) + { + return false; + } + } + } + } + } + + if( isPartialUpdate ) + { + if( dx1 < 0.0f ) + { + dx1 = 0.0f; + } + if( dy1 < 0.0f ) + { + dy1 = 0.0f; + } + if( dx2 > viewportRect.width ) + { + dx2 = viewportRect.width; + } + if( dy2 > viewportRect.height ) + { + dy2 = viewportRect.height; + } + + damagedRect.x = dx1; + damagedRect.y = dy1; + damagedRect.width = dx2 - dx1; + damagedRect.height = dy2 - dy1; + } + + return isPartialUpdate; +} + void RenderManager::DoRender( RenderInstruction& instruction ) { Rect viewportRect; Vector4 clearColor; + bool isPartialUpdate = false; + Rect damagedRect; + Rect mergedRect; + Dali::ClippingBox scissorBox; + Dali::ClippingBox intersectRect; if ( instruction.mIsClearColorSet ) { @@ -611,6 +724,7 @@ void RenderManager::DoRender( RenderInstruction& instruction ) Vector4 backgroundColor = mImpl->backgroundColor; Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable; Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable; + Integration::PartialUpdateAvailable partialUpdateAvailable = mImpl->partialUpdateAvailable; Render::SurfaceFrameBuffer* surfaceFrameBuffer = nullptr; if ( instruction.mFrameBuffer != 0 ) @@ -676,25 +790,64 @@ void RenderManager::DoRender( RenderInstruction& instruction ) mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u ); } + + if( surfaceFrameBuffer && + partialUpdateAvailable == Integration::PartialUpdateAvailable::TRUE ) + { + const RenderListContainer::SizeType renderListCount = instruction.RenderListCount(); + // Iterate through each render list. + if( surfaceFrameBuffer->IsPartialUpdateEnabled() ) + { + isPartialUpdate = GetDamagedRect( surfaceRect, instruction, damagedRect ) ; + } + + if( !isPartialUpdate ) + { + damagedRect = surfaceRect; + } + + mergedRect = surfaceFrameBuffer->SetDamagedRect( damagedRect ); + + if( mergedRect.IsEmpty() ) + { + isPartialUpdate = false; + } + else + { + scissorBox.x = mergedRect.x; + scissorBox.y = mergedRect.y; + scissorBox.width = mergedRect.width; + scissorBox.height = mergedRect.height; + } + } + if ( surfaceFrameBuffer ) { - mImpl->currentContext->Viewport( surfaceRect.x, - surfaceRect.y, - surfaceRect.width, - surfaceRect.height ); + mImpl->currentContext->Viewport( surfaceRect.x, + surfaceRect.y, + surfaceRect.width, + surfaceRect.height ); + - mImpl->currentContext->ClearColor( backgroundColor.r, - backgroundColor.g, - backgroundColor.b, - backgroundColor.a ); + mImpl->currentContext->ClearColor( backgroundColor.r, + backgroundColor.g, + backgroundColor.b, + backgroundColor.a ); } // Clear the entire color, depth and stencil buffers for the default framebuffer, if required. // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit", // and then stall. That problem is only noticeable when rendering a large number of vertices per frame. - - mImpl->currentContext->SetScissorTest( false ); + if( isPartialUpdate ) + { + mImpl->currentContext->SetScissorTest( true ); + mImpl->currentContext->Scissor( scissorBox.x, scissorBox.y, scissorBox.width, scissorBox.height ); + } + else + { + mImpl->currentContext->SetScissorTest( false ); + } GLbitfield clearMask = GL_COLOR_BUFFER_BIT; @@ -715,6 +868,12 @@ void RenderManager::DoRender( RenderInstruction& instruction ) mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR ); + if( isPartialUpdate ) + { + mImpl->currentContext->SetScissorTest( false ); + } + + if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) ) { if ( instruction.mFrameBuffer->IsSurfaceBacked() ) // Surface rendering @@ -786,7 +945,15 @@ void RenderManager::DoRender( RenderInstruction& instruction ) // Clear the viewport area only mImpl->currentContext->SetScissorTest( true ); - mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height ); + if( isPartialUpdate ) + { + intersectRect = IntersectAABB( scissorBox, viewportRect ); + mImpl->currentContext->Scissor( intersectRect.x, intersectRect.y, intersectRect.width, intersectRect.height ); + } + else + { + mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height ); + } mImpl->currentContext->ColorMask( true ); mImpl->currentContext->Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES ); mImpl->currentContext->SetScissorTest( false ); @@ -802,7 +969,8 @@ void RenderManager::DoRender( RenderInstruction& instruction ) depthBufferAvailable, stencilBufferAvailable, mImpl->boundTextures, - surfaceOrientation ); + surfaceOrientation, + scissorBox ); // Synchronise the FBO/Texture access when there are multiple contexts if ( mImpl->currentContext->IsSurfacelessContextSupported() )